1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //! Integration tests of the library libfdt.
18 
19 use core::ffi::CStr;
20 use cstr::cstr;
21 use libfdt::{Fdt, FdtError, FdtNodeMut, Phandle};
22 use std::collections::HashSet;
23 use std::ffi::CString;
24 use std::fs;
25 use std::ops::Range;
26 
27 const TEST_TREE_WITH_ONE_MEMORY_RANGE_PATH: &str = "data/test_tree_one_memory_range.dtb";
28 const TEST_TREE_WITH_MULTIPLE_MEMORY_RANGES_PATH: &str =
29     "data/test_tree_multiple_memory_ranges.dtb";
30 const TEST_TREE_WITH_EMPTY_MEMORY_RANGE_PATH: &str = "data/test_tree_empty_memory_range.dtb";
31 const TEST_TREE_WITH_NO_MEMORY_NODE_PATH: &str = "data/test_tree_no_memory_node.dtb";
32 const TEST_TREE_PHANDLE_PATH: &str = "data/test_tree_phandle.dtb";
33 
34 #[test]
retrieving_memory_from_fdt_with_one_memory_range_succeeds()35 fn retrieving_memory_from_fdt_with_one_memory_range_succeeds() {
36     let data = fs::read(TEST_TREE_WITH_ONE_MEMORY_RANGE_PATH).unwrap();
37     let fdt = Fdt::from_slice(&data).unwrap();
38 
39     const EXPECTED_FIRST_MEMORY_RANGE: Range<usize> = 0..256;
40     let mut memory = fdt.memory().unwrap();
41     assert_eq!(memory.next(), Some(EXPECTED_FIRST_MEMORY_RANGE));
42     assert_eq!(memory.next(), None);
43     assert_eq!(fdt.first_memory_range(), Ok(EXPECTED_FIRST_MEMORY_RANGE));
44 }
45 
46 #[test]
retrieving_memory_from_fdt_with_multiple_memory_ranges_succeeds()47 fn retrieving_memory_from_fdt_with_multiple_memory_ranges_succeeds() {
48     let data = fs::read(TEST_TREE_WITH_MULTIPLE_MEMORY_RANGES_PATH).unwrap();
49     let fdt = Fdt::from_slice(&data).unwrap();
50 
51     const EXPECTED_FIRST_MEMORY_RANGE: Range<usize> = 0..256;
52     const EXPECTED_SECOND_MEMORY_RANGE: Range<usize> = 512..1024;
53     let mut memory = fdt.memory().unwrap();
54     assert_eq!(memory.next(), Some(EXPECTED_FIRST_MEMORY_RANGE));
55     assert_eq!(memory.next(), Some(EXPECTED_SECOND_MEMORY_RANGE));
56     assert_eq!(memory.next(), None);
57     assert_eq!(fdt.first_memory_range(), Ok(EXPECTED_FIRST_MEMORY_RANGE));
58 }
59 
60 #[test]
retrieving_first_memory_from_fdt_with_empty_memory_range_fails()61 fn retrieving_first_memory_from_fdt_with_empty_memory_range_fails() {
62     let data = fs::read(TEST_TREE_WITH_EMPTY_MEMORY_RANGE_PATH).unwrap();
63     let fdt = Fdt::from_slice(&data).unwrap();
64 
65     let mut memory = fdt.memory().unwrap();
66     assert_eq!(memory.next(), None);
67     assert_eq!(fdt.first_memory_range(), Err(FdtError::NotFound));
68 }
69 
70 #[test]
retrieving_memory_from_fdt_with_no_memory_node_fails()71 fn retrieving_memory_from_fdt_with_no_memory_node_fails() {
72     let data = fs::read(TEST_TREE_WITH_NO_MEMORY_NODE_PATH).unwrap();
73     let fdt = Fdt::from_slice(&data).unwrap();
74 
75     assert_eq!(fdt.memory().unwrap_err(), FdtError::NotFound);
76     assert_eq!(fdt.first_memory_range(), Err(FdtError::NotFound));
77 }
78 
79 #[test]
node_name()80 fn node_name() {
81     let data = fs::read(TEST_TREE_WITH_NO_MEMORY_NODE_PATH).unwrap();
82     let fdt = Fdt::from_slice(&data).unwrap();
83 
84     let root = fdt.root();
85     assert_eq!(root.name(), Ok(cstr!("")));
86 
87     let chosen = fdt.chosen().unwrap().unwrap();
88     assert_eq!(chosen.name(), Ok(cstr!("chosen")));
89 
90     let nested_node_path = cstr!("/cpus/PowerPC,970@0");
91     let nested_node = fdt.node(nested_node_path).unwrap().unwrap();
92     assert_eq!(nested_node.name(), Ok(cstr!("PowerPC,970@0")));
93 }
94 
95 #[test]
node_subnodes()96 fn node_subnodes() {
97     let data = fs::read(TEST_TREE_WITH_NO_MEMORY_NODE_PATH).unwrap();
98     let fdt = Fdt::from_slice(&data).unwrap();
99     let root = fdt.root();
100     let expected = [Ok(cstr!("cpus")), Ok(cstr!("randomnode")), Ok(cstr!("chosen"))];
101 
102     let root_subnodes = root.subnodes().unwrap();
103     let subnode_names: Vec<_> = root_subnodes.map(|node| node.name()).collect();
104     assert_eq!(subnode_names, expected);
105 }
106 
107 #[test]
node_properties()108 fn node_properties() {
109     let data = fs::read(TEST_TREE_WITH_NO_MEMORY_NODE_PATH).unwrap();
110     let fdt = Fdt::from_slice(&data).unwrap();
111     let root = fdt.root();
112     let one_be = 0x1_u32.to_be_bytes();
113     type Result<T> = core::result::Result<T, FdtError>;
114     let expected: Vec<(Result<&CStr>, Result<&[u8]>)> = vec![
115         (Ok(cstr!("model")), Ok(b"MyBoardName\0".as_ref())),
116         (Ok(cstr!("compatible")), Ok(b"MyBoardName\0MyBoardFamilyName\0".as_ref())),
117         (Ok(cstr!("#address-cells")), Ok(&one_be)),
118         (Ok(cstr!("#size-cells")), Ok(&one_be)),
119         (Ok(cstr!("empty_prop")), Ok(&[])),
120     ];
121 
122     let properties = root.properties().unwrap();
123     let subnode_properties: Vec<_> = properties.map(|prop| (prop.name(), prop.value())).collect();
124 
125     assert_eq!(subnode_properties, expected);
126 }
127 
128 #[test]
node_supernode_at_depth()129 fn node_supernode_at_depth() {
130     let data = fs::read(TEST_TREE_WITH_NO_MEMORY_NODE_PATH).unwrap();
131     let fdt = Fdt::from_slice(&data).unwrap();
132     let node = fdt.node(cstr!("/cpus/PowerPC,970@1")).unwrap().unwrap();
133     let expected = vec![Ok(cstr!("")), Ok(cstr!("cpus")), Ok(cstr!("PowerPC,970@1"))];
134 
135     let mut supernode_names = vec![];
136     let mut depth = 0;
137     while let Ok(supernode) = node.supernode_at_depth(depth) {
138         supernode_names.push(supernode.name());
139         depth += 1;
140     }
141 
142     assert_eq!(supernode_names, expected);
143 }
144 
145 #[test]
phandle_new()146 fn phandle_new() {
147     let valid_phandles = [
148         u32::from(Phandle::MIN),
149         u32::from(Phandle::MIN).checked_add(1).unwrap(),
150         0x55,
151         u32::from(Phandle::MAX).checked_sub(1).unwrap(),
152         u32::from(Phandle::MAX),
153     ];
154 
155     for value in valid_phandles {
156         let phandle = Phandle::new(value).unwrap();
157 
158         assert_eq!(value.try_into(), Ok(phandle));
159         assert_eq!(u32::from(phandle), value);
160     }
161 
162     let bad_phandles = [
163         u32::from(Phandle::MIN).checked_sub(1).unwrap(),
164         u32::from(Phandle::MAX).checked_add(1).unwrap(),
165     ];
166 
167     for value in bad_phandles {
168         assert_eq!(Phandle::new(value), None);
169         assert_eq!(Phandle::try_from(value), Err(FdtError::BadPhandle));
170     }
171 }
172 
173 #[test]
max_phandle()174 fn max_phandle() {
175     let data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
176     let fdt = Fdt::from_slice(&data).unwrap();
177     let phandle = Phandle::new(0xFF).unwrap();
178 
179     assert_eq!(fdt.max_phandle(), Ok(phandle));
180 }
181 
182 #[test]
node_with_phandle()183 fn node_with_phandle() {
184     let data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
185     let fdt = Fdt::from_slice(&data).unwrap();
186 
187     // Test linux,phandle
188     let phandle = Phandle::new(0xFF).unwrap();
189     let node = fdt.node_with_phandle(phandle).unwrap().unwrap();
190     assert_eq!(node.name(), Ok(cstr!("node_zz")));
191 
192     // Test phandle
193     let phandle = Phandle::new(0x22).unwrap();
194     let node = fdt.node_with_phandle(phandle).unwrap().unwrap();
195     assert_eq!(node.name(), Ok(cstr!("node_abc")));
196 }
197 
198 #[test]
node_mut_with_phandle()199 fn node_mut_with_phandle() {
200     let mut data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
201     let fdt = Fdt::from_mut_slice(&mut data).unwrap();
202 
203     // Test linux,phandle
204     let phandle = Phandle::new(0xFF).unwrap();
205     let node: FdtNodeMut = fdt.node_mut_with_phandle(phandle).unwrap().unwrap();
206     assert_eq!(node.as_node().name(), Ok(cstr!("node_zz")));
207 
208     // Test phandle
209     let phandle = Phandle::new(0x22).unwrap();
210     let node: FdtNodeMut = fdt.node_mut_with_phandle(phandle).unwrap().unwrap();
211     assert_eq!(node.as_node().name(), Ok(cstr!("node_abc")));
212 }
213 
214 #[test]
node_get_phandle()215 fn node_get_phandle() {
216     let data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
217     let fdt = Fdt::from_slice(&data).unwrap();
218 
219     // Test linux,phandle
220     let node = fdt.node(cstr!("/node_z/node_zz")).unwrap().unwrap();
221     assert_eq!(node.get_phandle(), Ok(Phandle::new(0xFF)));
222 
223     // Test phandle
224     let node = fdt.node(cstr!("/node_a/node_ab/node_abc")).unwrap().unwrap();
225     assert_eq!(node.get_phandle(), Ok(Phandle::new(0x22)));
226 
227     // Test no phandle
228     let node = fdt.node(cstr!("/node_b")).unwrap().unwrap();
229     assert_eq!(node.get_phandle(), Ok(None));
230 }
231 
232 #[test]
node_nop()233 fn node_nop() {
234     let mut data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
235     let fdt = Fdt::from_mut_slice(&mut data).unwrap();
236     let phandle = Phandle::new(0xFF).unwrap();
237     let path = cstr!("/node_z/node_zz");
238 
239     fdt.node_with_phandle(phandle).unwrap().unwrap();
240     let node = fdt.node_mut(path).unwrap().unwrap();
241 
242     node.nop().unwrap();
243 
244     assert_eq!(fdt.node_with_phandle(phandle), Ok(None));
245     assert_eq!(fdt.node(path), Ok(None));
246 
247     fdt.unpack().unwrap();
248     fdt.pack().unwrap();
249 
250     assert_eq!(fdt.node_with_phandle(phandle), Ok(None));
251     assert_eq!(fdt.node(path), Ok(None));
252 }
253 
254 #[test]
node_add_subnode_with_namelen()255 fn node_add_subnode_with_namelen() {
256     let mut data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
257     data.resize(data.len() * 2, 0_u8);
258 
259     let fdt = Fdt::from_mut_slice(&mut data).unwrap();
260     fdt.unpack().unwrap();
261 
262     let node_path = cstr!("/node_z/node_zz");
263     let subnode_name = cstr!("123456789");
264 
265     for len in 0..subnode_name.to_bytes().len() {
266         let name = &subnode_name.to_bytes()[0..len];
267         let node = fdt.node(node_path).unwrap().unwrap();
268         assert_eq!(Ok(None), node.subnode_with_name_bytes(name));
269 
270         let node = fdt.node_mut(node_path).unwrap().unwrap();
271         let _ = node.add_subnode_with_namelen(subnode_name, len).unwrap();
272 
273         let node = fdt.node(node_path).unwrap().unwrap();
274         assert_ne!(Ok(None), node.subnode_with_name_bytes(name));
275     }
276 
277     let node_path = node_path.to_str().unwrap();
278     for len in 1..subnode_name.to_bytes().len() {
279         let name = String::from_utf8(subnode_name.to_bytes()[..len].to_vec()).unwrap();
280         let path = CString::new(format!("{node_path}/{name}")).unwrap();
281         let name = CString::new(name).unwrap();
282         let subnode = fdt.node(&path).unwrap().unwrap();
283         assert_eq!(subnode.name(), Ok(name.as_c_str()));
284     }
285 }
286 
287 #[test]
node_subnode()288 fn node_subnode() {
289     let data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
290     let fdt = Fdt::from_slice(&data).unwrap();
291 
292     let name = cstr!("node_a");
293     let root = fdt.root();
294     let node = root.subnode(name).unwrap();
295     assert_ne!(None, node);
296     let node = node.unwrap();
297 
298     assert_eq!(Ok(name), node.name());
299 }
300 
301 #[test]
node_subnode_with_name_bytes()302 fn node_subnode_with_name_bytes() {
303     let data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
304     let fdt = Fdt::from_slice(&data).unwrap();
305 
306     let name = b"node_aaaaa";
307     let root = fdt.root();
308     let node = root.subnode_with_name_bytes(&name[0..6]).unwrap();
309     assert_ne!(None, node);
310     let node = node.unwrap();
311 
312     assert_eq!(Ok(cstr!("node_a")), node.name());
313 }
314 
315 #[test]
node_subnode_borrow_checker()316 fn node_subnode_borrow_checker() {
317     let data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
318     let fdt = Fdt::from_slice(&data).unwrap();
319 
320     let name = cstr!("node_a");
321     let node = {
322         let root = fdt.root();
323         root.subnode(name).unwrap().unwrap()
324     };
325 
326     assert_eq!(Ok(name), node.name());
327 }
328 
329 #[test]
fdt_symbols()330 fn fdt_symbols() {
331     let mut data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
332     let fdt = Fdt::from_mut_slice(&mut data).unwrap();
333 
334     let symbols = fdt.symbols().unwrap().unwrap();
335     assert_eq!(symbols.name(), Ok(cstr!("__symbols__")));
336 
337     // Validates type.
338     let _symbols: FdtNodeMut = fdt.symbols_mut().unwrap().unwrap();
339 }
340 
341 #[test]
node_mut_as_node()342 fn node_mut_as_node() {
343     let mut data = fs::read(TEST_TREE_WITH_ONE_MEMORY_RANGE_PATH).unwrap();
344     let fdt = Fdt::from_mut_slice(&mut data).unwrap();
345 
346     let mut memory = fdt.node_mut(cstr!("/memory")).unwrap().unwrap();
347     {
348         let memory = memory.as_node();
349         assert_eq!(memory.name(), Ok(cstr!("memory")));
350     }
351 
352     // Just check whether borrow checker doesn't complain this.
353     memory.setprop_inplace(cstr!("device_type"), b"MEMORY\0").unwrap();
354 }
355 
356 #[test]
node_descendants()357 fn node_descendants() {
358     let mut data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
359     let fdt = Fdt::from_mut_slice(&mut data).unwrap();
360 
361     let node_z = fdt.node(cstr!("/node_z")).unwrap().unwrap();
362     let descendants: Vec<_> =
363         node_z.descendants().map(|(node, depth)| (node.name().unwrap(), depth)).collect();
364 
365     assert_eq!(
366         descendants,
367         vec![
368             (cstr!("node_za"), 1),
369             (cstr!("node_zb"), 1),
370             (cstr!("node_zz"), 1),
371             (cstr!("node_zzz"), 2)
372         ]
373     );
374 }
375 
376 #[test]
node_mut_delete_and_next_subnode()377 fn node_mut_delete_and_next_subnode() {
378     let mut data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
379     let fdt = Fdt::from_mut_slice(&mut data).unwrap();
380 
381     let root = fdt.root_mut();
382     let mut subnode_iter = root.first_subnode().unwrap();
383 
384     while let Some(subnode) = subnode_iter {
385         if subnode.as_node().name() == Ok(cstr!("node_z")) {
386             subnode_iter = subnode.delete_and_next_subnode().unwrap();
387         } else {
388             subnode_iter = subnode.next_subnode().unwrap();
389         }
390     }
391 
392     let root = fdt.root();
393     let expected_names = vec![
394         Ok(cstr!("node_a")),
395         Ok(cstr!("node_b")),
396         Ok(cstr!("node_c")),
397         Ok(cstr!("__symbols__")),
398     ];
399     let subnode_names: Vec<_> = root.subnodes().unwrap().map(|node| node.name()).collect();
400 
401     assert_eq!(expected_names, subnode_names);
402 }
403 
404 #[test]
node_mut_delete_and_next_node()405 fn node_mut_delete_and_next_node() {
406     let mut data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
407     let fdt = Fdt::from_mut_slice(&mut data).unwrap();
408 
409     let expected_nodes = vec![
410         (Ok(cstr!("node_b")), 1),
411         (Ok(cstr!("node_c")), 1),
412         (Ok(cstr!("node_z")), 1),
413         (Ok(cstr!("node_za")), 2),
414         (Ok(cstr!("node_zb")), 2),
415         (Ok(cstr!("__symbols__")), 1),
416     ];
417 
418     let mut expected_nodes_iter = expected_nodes.iter();
419     let mut iter = fdt.root_mut().next_node(0).unwrap();
420     while let Some((node, depth)) = iter {
421         let node_name = node.as_node().name();
422         if node_name == Ok(cstr!("node_a")) || node_name == Ok(cstr!("node_zz")) {
423             iter = node.delete_and_next_node(depth).unwrap();
424         } else {
425             // Note: Checking name here is easier than collecting names and assert_eq!(),
426             //       because we can't keep name references while iterating with FdtNodeMut.
427             let expected_node = expected_nodes_iter.next();
428             assert_eq!(expected_node, Some(&(node_name, depth)));
429             iter = node.next_node(depth).unwrap();
430         }
431     }
432     assert_eq!(None, expected_nodes_iter.next());
433 
434     let root = fdt.root();
435     let all_descendants: Vec<_> =
436         root.descendants().map(|(node, depth)| (node.name(), depth)).collect();
437     assert_eq!(expected_nodes, all_descendants);
438 }
439 
440 #[test]
node_mut_delete_and_next_node_with_last_node()441 fn node_mut_delete_and_next_node_with_last_node() {
442     let mut data = fs::read(TEST_TREE_WITH_EMPTY_MEMORY_RANGE_PATH).unwrap();
443     let fdt = Fdt::from_mut_slice(&mut data).unwrap();
444 
445     let mut iter = fdt.root_mut().next_node(0).unwrap();
446     while let Some((node, depth)) = iter {
447         iter = node.delete_and_next_node(depth).unwrap();
448     }
449 
450     let root = fdt.root();
451     let all_descendants: Vec<_> =
452         root.descendants().map(|(node, depth)| (node.name(), depth)).collect();
453     assert!(all_descendants.is_empty(), "{all_descendants:?}");
454 }
455 
456 #[test]
457 #[ignore] // Borrow checker test. Compilation success is sufficient.
node_name_lifetime()458 fn node_name_lifetime() {
459     let data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
460     let fdt = Fdt::from_slice(&data).unwrap();
461 
462     let name = {
463         let root = fdt.root();
464         root.name()
465         // Make root to be dropped
466     };
467     assert_eq!(Ok(cstr!("")), name);
468 }
469 
470 #[test]
node_mut_add_subnodes()471 fn node_mut_add_subnodes() {
472     let mut data = vec![0_u8; 1000];
473     let fdt = Fdt::create_empty_tree(&mut data).unwrap();
474 
475     let root = fdt.root_mut();
476     let names = [cstr!("a"), cstr!("b")];
477     root.add_subnodes(&names).unwrap();
478 
479     let expected: HashSet<_> = names.into_iter().collect();
480     let subnodes = fdt.root().subnodes().unwrap();
481     let names: HashSet<_> = subnodes.map(|node| node.name().unwrap()).collect();
482 
483     assert_eq!(expected, names);
484 }
485 
486 #[test]
487 #[ignore] // Borrow checker test. Compilation success is sufficient.
node_subnode_lifetime()488 fn node_subnode_lifetime() {
489     let data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
490     let fdt = Fdt::from_slice(&data).unwrap();
491 
492     let name = {
493         let node_a = {
494             let root = fdt.root();
495             root.subnode(cstr!("node_a")).unwrap()
496             // Make root to be dropped
497         };
498         assert_ne!(None, node_a);
499         node_a.unwrap().name()
500         // Make node_a to be dropped
501     };
502     assert_eq!(Ok(cstr!("node_a")), name);
503 }
504 
505 #[test]
506 #[ignore] // Borrow checker test. Compilation success is sufficient.
node_subnodess_lifetime()507 fn node_subnodess_lifetime() {
508     let data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
509     let fdt = Fdt::from_slice(&data).unwrap();
510 
511     let first_subnode_name = {
512         let first_subnode = {
513             let mut subnodes_iter = {
514                 let root = fdt.root();
515                 root.subnodes().unwrap()
516                 // Make root to be dropped
517             };
518             subnodes_iter.next().unwrap()
519             // Make subnodess_iter to be dropped
520         };
521         first_subnode.name()
522         // Make first_subnode to be dropped
523     };
524     assert_eq!(Ok(cstr!("node_a")), first_subnode_name);
525 }
526 
527 #[test]
528 #[ignore] // Borrow checker test. Compilation success is sufficient.
node_descendants_lifetime()529 fn node_descendants_lifetime() {
530     let data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
531     let fdt = Fdt::from_slice(&data).unwrap();
532 
533     let first_descendant_name = {
534         let (first_descendant, _) = {
535             let mut descendants_iter = {
536                 let root = fdt.root();
537                 root.descendants()
538                 // Make root to be dropped
539             };
540             descendants_iter.next().unwrap()
541             // Make descendants_iter to be dropped
542         };
543         first_descendant.name()
544         // Make first_descendant to be dropped
545     };
546     assert_eq!(Ok(cstr!("node_a")), first_descendant_name);
547 }
548