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