1 // Copyright 2024, The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //! GblOps trait that defines device tree components helpers. 16 17 use crate::{gbl_print, gbl_println, GblOps}; 18 use arrayvec::ArrayVec; 19 use dttable::{DtTableImage, DtTableMetadata}; 20 use fdt::{Fdt, FdtHeader, FDT_HEADER_SIZE}; 21 use liberror::{Error, Result}; 22 use libutils::aligned_subslice; 23 24 /// Device tree alignment. 25 pub const FDT_ALIGNMENT: usize = 8; 26 /// Maximum amount of device tree components GBL can handle to select from. 27 /// TODO(b/353272981): Use dynamic memory to store components. Currently 28 /// DeviceTreeComponentsRegistry takes about 18kb of stack, which can be slow and dangerous. 29 pub const MAXIMUM_DEVICE_TREE_COMPONENTS: usize = 256; 30 /// Error message to fail in case of unsupported amount of device tree components. 31 pub const MAXIMUM_DEVICE_TREE_COMPONENTS_ERROR_MSG: &str = 32 "At most 256 device components are supported to build the final one"; 33 34 /// The source device tree component is coming from. 35 #[derive(Copy, Clone, Eq, PartialEq, Debug)] 36 pub enum DeviceTreeComponentSource { 37 /// Loaded from Boot partition. 38 Boot, 39 /// Loaded from Vendor Boot partition. 40 VendorBoot, 41 /// Loaded from DTB partition. 42 Dtb(DtTableMetadata), 43 /// Loaded from DTBO partition. 44 Dtbo(DtTableMetadata), 45 } 46 47 impl core::fmt::Display for DeviceTreeComponentSource { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result48 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 49 match self { 50 DeviceTreeComponentSource::Boot => write!(f, "Boot"), 51 DeviceTreeComponentSource::VendorBoot => write!(f, "VendorBoot"), 52 DeviceTreeComponentSource::Dtb(_) => write!(f, "Dtb"), 53 DeviceTreeComponentSource::Dtbo(_) => write!(f, "Dtbo"), 54 } 55 } 56 } 57 58 /// Device tree component (device tree or overlay) to build the final one. 59 #[derive(Copy, Clone, Eq, PartialEq, Debug)] 60 pub struct DeviceTreeComponent<'a> { 61 /// Source the component is loaded from. 62 pub source: DeviceTreeComponentSource, 63 /// Device tree component payload. Must be 8 bytes aligned. 64 pub dt: &'a [u8], 65 /// Device tree component is selected. 66 pub selected: bool, 67 } 68 69 /// Maintain, select and get the device tree components to build the final device tree. 70 pub struct DeviceTreeComponentsRegistry<'a> { 71 components: ArrayVec<DeviceTreeComponent<'a>, MAXIMUM_DEVICE_TREE_COMPONENTS>, 72 /// `selected_overlays` array is used to return selected overlays as a sequential reference 73 /// slice. It must only be used within the `selected()` method and must not be assumed 74 /// valid elsewhere. 75 selected_overlays: ArrayVec<&'a [u8], MAXIMUM_DEVICE_TREE_COMPONENTS>, 76 } 77 78 impl<'a> DeviceTreeComponent<'a> { 79 /// Whether device tree component is base device tree or overlay. is_base_device_tree(&self) -> bool80 pub fn is_base_device_tree(&self) -> bool { 81 matches!( 82 self.source, 83 DeviceTreeComponentSource::Boot 84 | DeviceTreeComponentSource::VendorBoot 85 | DeviceTreeComponentSource::Dtb(_) 86 ) 87 } 88 } 89 90 impl<'a> DeviceTreeComponentsRegistry<'a> { 91 /// Create new empty DeviceTreeComponentsRegistry. new() -> Self92 pub fn new() -> Self { 93 DeviceTreeComponentsRegistry { 94 components: ArrayVec::new(), 95 selected_overlays: ArrayVec::new(), 96 } 97 } 98 99 /// Load device tree components from a dt table image. Ensure components are 8 bytes 100 /// aligned by using provided buffer to cut from. Returns remain buffer. append_from_dttable<'b>( &mut self, is_dtb: bool, dttable: &DtTableImage<'b>, buffer: &'a mut [u8], ) -> Result<&'a mut [u8]>101 fn append_from_dttable<'b>( 102 &mut self, 103 is_dtb: bool, 104 dttable: &DtTableImage<'b>, 105 buffer: &'a mut [u8], 106 ) -> Result<&'a mut [u8]> { 107 if dttable.entries_count() > self.components.remaining_capacity() { 108 return Err(Error::Other(Some(MAXIMUM_DEVICE_TREE_COMPONENTS_ERROR_MSG))); 109 } 110 111 let mut remains = buffer; 112 for entry in dttable.entries() { 113 // TODO(b/374336105): Find a better way to handle 8-bytes alignment rather than copy. 114 let (aligned_buffer, rest) = aligned_subslice(remains, FDT_ALIGNMENT)? 115 .split_at_mut_checked(entry.dtb.len()) 116 .ok_or(Error::Other(Some( 117 "Provided buffer is too small to ensure dttable entry is aligned", 118 )))?; 119 aligned_buffer.copy_from_slice(entry.dtb); 120 121 self.components.push(DeviceTreeComponent { 122 source: if is_dtb { 123 DeviceTreeComponentSource::Dtb(entry.metadata) 124 } else { 125 DeviceTreeComponentSource::Dtbo(entry.metadata) 126 }, 127 dt: aligned_buffer, 128 selected: false, 129 }); 130 131 remains = rest; 132 } 133 134 Ok(remains) 135 } 136 137 /// Load device tree components from a dtbo image. Ensure components are 8 bytes 138 /// aligned by using provided `buffer` to cut from. Returns remain buffer. append_from_dtbo<'b>( &mut self, dttable: &DtTableImage<'b>, buffer: &'a mut [u8], ) -> Result<&'a mut [u8]>139 pub fn append_from_dtbo<'b>( 140 &mut self, 141 dttable: &DtTableImage<'b>, 142 buffer: &'a mut [u8], 143 ) -> Result<&'a mut [u8]> { 144 self.append_from_dttable(false, dttable, buffer) 145 } 146 147 /// Append additional device trees from the buffer, where they are stored sequentially. 148 /// Ensure components are 8 bytes aligned by using provided buffer to cut from. Returns remain 149 /// buffer. 150 /// TODO(b/363244924): Remove after partners migrated to DTB. append_from_multifdt_buffer<'b, 'c>( &mut self, ops: &mut impl GblOps<'b, 'c>, source: DeviceTreeComponentSource, data: &'a [u8], buffer: &'a mut [u8], ) -> Result<&'a mut [u8]>151 fn append_from_multifdt_buffer<'b, 'c>( 152 &mut self, 153 ops: &mut impl GblOps<'b, 'c>, 154 source: DeviceTreeComponentSource, 155 data: &'a [u8], 156 buffer: &'a mut [u8], 157 ) -> Result<&'a mut [u8]> { 158 let mut components_added = 0; 159 let mut data_remains = data; 160 let mut buffer_remains = buffer; 161 while data_remains.len() >= FDT_HEADER_SIZE { 162 let aligned_buffer = aligned_subslice(buffer_remains, FDT_ALIGNMENT)?; 163 164 let header_slice = aligned_buffer.get_mut(..FDT_HEADER_SIZE).ok_or(Error::Other( 165 Some("Provided buffer is too small to ensure multidt entry is aligned"), 166 ))?; 167 // Fdt header must be aligned, so copy to an aligned buffer. 168 header_slice.copy_from_slice(&data_remains[..FDT_HEADER_SIZE]); 169 let next_fdt_size = FdtHeader::from_bytes_ref(header_slice)?.totalsize(); 170 171 if self.components.is_full() { 172 return Err(Error::Other(Some(MAXIMUM_DEVICE_TREE_COMPONENTS_ERROR_MSG))); 173 } 174 175 // Cut fdt and temporary buffers to make sure result fdt is 8 bytes aligned 176 let (data_buffer, data_buffer_remains) = 177 data_remains.split_at_checked(next_fdt_size).ok_or(Error::Other(Some( 178 "Multidt structure has a valid header but doesn't have a device tree payload", 179 )))?; 180 let (aligned_buffer, aligned_buffer_remains) = 181 aligned_buffer.split_at_mut_checked(next_fdt_size).ok_or(Error::Other(Some( 182 "Provided buffer is too small to ensure multidt entry is aligned", 183 )))?; 184 aligned_buffer.copy_from_slice(data_buffer); 185 186 Fdt::new(&aligned_buffer)?; 187 self.components.push(DeviceTreeComponent { 188 source: source, 189 dt: &aligned_buffer[..], 190 selected: false, 191 }); 192 193 components_added += 1; 194 data_remains = data_buffer_remains; 195 buffer_remains = aligned_buffer_remains; 196 } 197 198 if components_added > 0 { 199 gbl_println!( 200 ops, 201 "WARNING: {} additional device trees detected in {}. This is only temporarily \ 202 supported in GBL. Please migrate to the DTB partition to provide multiple device \ 203 trees for selection.", 204 components_added, 205 source, 206 ); 207 } 208 209 Ok(buffer_remains) 210 } 211 212 /// Append device tree components from provided buffer prefix. `fdt` must be a 8 bytes aligned 213 /// valid fdt buffer. `fdt` may also have multiple fdt buffers placed sequentially. Ensure each 214 /// of such components are 8 bytes aligned by using provided `buffer` to cut from. Returns 215 /// remain buffer. 216 /// TODO(b/363244924): Remove multiple fdt support after partners migrated to DTB. append<'b, 'c>( &mut self, ops: &mut impl GblOps<'b, 'c>, source: DeviceTreeComponentSource, fdt: &'a [u8], buffer: &'a mut [u8], ) -> Result<&'a mut [u8]>217 pub fn append<'b, 'c>( 218 &mut self, 219 ops: &mut impl GblOps<'b, 'c>, 220 source: DeviceTreeComponentSource, 221 fdt: &'a [u8], 222 buffer: &'a mut [u8], 223 ) -> Result<&'a mut [u8]> { 224 if self.components.is_full() { 225 return Err(Error::Other(Some(MAXIMUM_DEVICE_TREE_COMPONENTS_ERROR_MSG))); 226 } 227 228 let header = FdtHeader::from_bytes_ref(fdt)?; 229 let (fdt_buffer, fdt_remains) = fdt.split_at(header.totalsize()); 230 self.components.push(DeviceTreeComponent { 231 source: source, 232 dt: fdt_buffer, 233 selected: false, 234 }); 235 236 // TODO(b/363244924): Remove after partners migrated to DTB. 237 self.append_from_multifdt_buffer(ops, source, fdt_remains, buffer) 238 } 239 240 /// Default implementation of selected logic in case external one isn't provided. 241 /// Only base device tree is supported to choose from. Otherwise fail. No overlays will be 242 /// selected. autoselect(&mut self) -> Result<()>243 pub fn autoselect(&mut self) -> Result<()> { 244 let base_device_tree_count = 245 self.components.iter().filter(|component| component.is_base_device_tree()).count(); 246 if base_device_tree_count > 1 { 247 return Err(Error::Other(Some( 248 "Base device tree autoselection isn't supported if multiple device trees are \ 249 provided", 250 ))); 251 } 252 253 let base = self 254 .components 255 .iter_mut() 256 .find(|component| component.is_base_device_tree()) 257 .ok_or(Error::Other(Some("0 base device trees to autoselect from")))?; 258 base.selected = true; 259 260 Ok(()) 261 } 262 263 /// Return selected base device tree and overlays to apply. Fail in case selection isn't 264 /// correct. For correctness rules refer to `GblOps.select_device_trees` requirements. selected(&mut self) -> Result<(&[u8], &[&[u8]])>265 pub fn selected(&mut self) -> Result<(&[u8], &[&[u8]])> { 266 let base_device_tree_count = self 267 .components 268 .iter() 269 .filter(|component| component.is_base_device_tree() && component.selected) 270 .count(); 271 if base_device_tree_count > 1 { 272 return Err(Error::Other(Some("More than 1 base device tree is selected"))); 273 } 274 275 let base = self 276 .components 277 .iter() 278 .find(|component| component.is_base_device_tree() && component.selected) 279 .ok_or(Error::Other(Some("0 base device trees are selected")))?; 280 281 self.selected_overlays = self 282 .components 283 .iter() 284 .filter(|component| !component.is_base_device_tree() && component.selected) 285 .map(|component| component.dt) 286 .collect(); 287 288 Ok((base.dt, &self.selected_overlays[..])) 289 } 290 291 /// Iterator over components. components(&self) -> impl Iterator<Item = &DeviceTreeComponent<'a>>292 pub fn components(&self) -> impl Iterator<Item = &DeviceTreeComponent<'a>> { 293 self.components.iter() 294 } 295 296 /// Mutable iterator over components. components_mut(&mut self) -> impl Iterator<Item = &mut DeviceTreeComponent<'a>>297 pub fn components_mut(&mut self) -> impl Iterator<Item = &mut DeviceTreeComponent<'a>> { 298 self.components.iter_mut() 299 } 300 } 301 302 #[cfg(test)] 303 pub(crate) mod test { 304 use super::*; 305 use crate::ops::test::FakeGblOps; 306 307 #[test] test_components_registry_empty()308 fn test_components_registry_empty() { 309 let registry = DeviceTreeComponentsRegistry::new(); 310 311 assert_eq!(registry.components().count(), 0); 312 } 313 314 #[test] test_components_registry_append_component()315 fn test_components_registry_append_component() { 316 let dt = include_bytes!("../../libfdt/test/data/base.dtb").to_vec(); 317 let mut buffer = vec![0u8; 2 * 1024 * 1024]; // 2 MB 318 let mut gbl_ops = FakeGblOps::new(&[]); 319 let mut registry = DeviceTreeComponentsRegistry::new(); 320 321 registry 322 .append(&mut gbl_ops, DeviceTreeComponentSource::Boot, &dt[..], &mut buffer) 323 .unwrap(); 324 325 assert_eq!(registry.components().count(), 1); 326 327 let component = registry.components().next().unwrap(); 328 329 assert_eq!( 330 component, 331 &DeviceTreeComponent { 332 source: DeviceTreeComponentSource::Boot, 333 dt: &dt[..], 334 selected: false, 335 } 336 ); 337 assert!(component.is_base_device_tree()); 338 } 339 340 #[test] test_components_registry_append_too_many_components()341 fn test_components_registry_append_too_many_components() { 342 let dt = include_bytes!("../../libfdt/test/data/base.dtb").to_vec(); 343 let mut buffer = vec![0u8; 2 * 1024 * 1024]; // 2 MB 344 let mut gbl_ops = FakeGblOps::new(&[]); 345 let mut registry = DeviceTreeComponentsRegistry::new(); 346 347 let mut current_buffer = &mut buffer[..]; 348 // Fill the whole reserved space 349 for _ in 0..MAXIMUM_DEVICE_TREE_COMPONENTS { 350 current_buffer = registry 351 .append(&mut gbl_ops, DeviceTreeComponentSource::Boot, &dt[..], current_buffer) 352 .unwrap(); 353 } 354 355 assert_eq!( 356 registry.append(&mut gbl_ops, DeviceTreeComponentSource::Boot, &dt[..], current_buffer), 357 Err(Error::Other(Some(MAXIMUM_DEVICE_TREE_COMPONENTS_ERROR_MSG))) 358 ); 359 } 360 361 #[test] test_components_append_from_dtbo()362 fn test_components_append_from_dtbo() { 363 let dttable = include_bytes!("../../libdttable/test/data/dttable.img").to_vec(); 364 let mut buffer = vec![0u8; 2 * 1024 * 1024]; // 2 MB 365 let mut registry = DeviceTreeComponentsRegistry::new(); 366 367 let table = DtTableImage::from_bytes(&dttable[..]).unwrap(); 368 registry.append_from_dtbo(&table, &mut buffer[..]).unwrap(); 369 370 // Check data is loaded 371 let components: Vec<_> = registry.components().cloned().collect(); 372 let expected_components: Vec<DeviceTreeComponent> = table 373 .entries() 374 .map(|e| DeviceTreeComponent { 375 source: DeviceTreeComponentSource::Dtbo(e.metadata), 376 dt: e.dtb, 377 selected: false, 378 }) 379 .collect(); 380 assert_eq!(components, expected_components); 381 382 // Check data is aligned 383 registry.components().for_each(|c| assert!(c.dt.as_ptr().align_offset(FDT_ALIGNMENT) == 0)); 384 } 385 386 #[test] test_components_returns_selected()387 fn test_components_returns_selected() { 388 let dt = include_bytes!("../../libfdt/test/data/base.dtb").to_vec(); 389 let mut buffer = vec![0u8; 2 * 1024 * 1024]; // 2 MB 390 let mut gbl_ops = FakeGblOps::new(&[]); 391 let mut registry = DeviceTreeComponentsRegistry::new(); 392 393 let sources = [ 394 DeviceTreeComponentSource::VendorBoot, 395 DeviceTreeComponentSource::Boot, 396 DeviceTreeComponentSource::Dtbo(Default::default()), 397 DeviceTreeComponentSource::Dtbo(Default::default()), 398 DeviceTreeComponentSource::Dtbo(Default::default()), 399 ]; 400 let mut current_buffer = &mut buffer[..]; 401 for source in sources.iter() { 402 current_buffer = registry.append(&mut gbl_ops, *source, &dt, current_buffer).unwrap(); 403 } 404 405 // Select base device tree 406 registry.components_mut().nth(1).unwrap().selected = true; 407 // Select first overlay 408 registry.components_mut().nth(2).unwrap().selected = true; 409 // Select second overlay 410 registry.components_mut().nth(3).unwrap().selected = true; 411 412 let expected_overlays = 413 &[registry.components().nth(2).unwrap().dt, registry.components().nth(3).unwrap().dt]; 414 // Expected selected data 415 let expected_selected = (registry.components().nth(1).unwrap().dt, &expected_overlays[..]); 416 417 assert_eq!(registry.selected().unwrap(), expected_selected); 418 } 419 420 #[test] test_components_returns_selected_no_overlays()421 fn test_components_returns_selected_no_overlays() { 422 let dt = include_bytes!("../../libfdt/test/data/base.dtb").to_vec(); 423 let mut buffer = vec![0u8; 2 * 1024 * 1024]; // 2 MB 424 let mut gbl_ops = FakeGblOps::new(&[]); 425 let mut registry = DeviceTreeComponentsRegistry::new(); 426 427 let sources = [ 428 DeviceTreeComponentSource::VendorBoot, 429 DeviceTreeComponentSource::Boot, 430 DeviceTreeComponentSource::Dtbo(Default::default()), 431 DeviceTreeComponentSource::Dtbo(Default::default()), 432 DeviceTreeComponentSource::Dtbo(Default::default()), 433 ]; 434 let mut current_buffer = &mut buffer[..]; 435 for source in sources.iter() { 436 current_buffer = registry.append(&mut gbl_ops, *source, &dt, current_buffer).unwrap(); 437 } 438 439 // Select base device tree 440 registry.components_mut().nth(1).unwrap().selected = true; 441 442 // Expected selected data 443 let expected_selected = (registry.components().nth(1).unwrap().dt, &[][..]); 444 445 assert_eq!(registry.selected().unwrap(), expected_selected); 446 } 447 448 #[test] test_components_returns_no_base_device_tree_failed()449 fn test_components_returns_no_base_device_tree_failed() { 450 let dt = include_bytes!("../../libfdt/test/data/base.dtb").to_vec(); 451 let mut buffer = vec![0u8; 2 * 1024 * 1024]; // 2 MB 452 let mut gbl_ops = FakeGblOps::new(&[]); 453 let mut registry = DeviceTreeComponentsRegistry::new(); 454 455 let sources = [ 456 DeviceTreeComponentSource::VendorBoot, 457 DeviceTreeComponentSource::Boot, 458 DeviceTreeComponentSource::Dtbo(Default::default()), 459 DeviceTreeComponentSource::Dtbo(Default::default()), 460 DeviceTreeComponentSource::Dtbo(Default::default()), 461 ]; 462 let mut current_buffer = &mut buffer[..]; 463 for source in sources.iter() { 464 current_buffer = registry.append(&mut gbl_ops, *source, &dt, current_buffer).unwrap(); 465 } 466 467 // Select first overlay 468 registry.components_mut().nth(2).unwrap().selected = true; 469 // Select second overlay 470 registry.components_mut().nth(3).unwrap().selected = true; 471 472 assert!(registry.selected().is_err()); 473 } 474 475 #[test] test_components_returns_multiple_base_device_trees_failed()476 fn test_components_returns_multiple_base_device_trees_failed() { 477 let dt = include_bytes!("../../libfdt/test/data/base.dtb").to_vec(); 478 let mut buffer = vec![0u8; 2 * 1024 * 1024]; // 2 MB 479 let mut gbl_ops = FakeGblOps::new(&[]); 480 let mut registry = DeviceTreeComponentsRegistry::new(); 481 482 let sources = [ 483 DeviceTreeComponentSource::VendorBoot, 484 DeviceTreeComponentSource::Boot, 485 DeviceTreeComponentSource::Dtbo(Default::default()), 486 DeviceTreeComponentSource::Dtbo(Default::default()), 487 DeviceTreeComponentSource::Dtbo(Default::default()), 488 ]; 489 let mut current_buffer = &mut buffer[..]; 490 for source in sources.iter() { 491 current_buffer = registry.append(&mut gbl_ops, *source, &dt, current_buffer).unwrap(); 492 } 493 494 // Select first base device tree 495 registry.components_mut().nth(0).unwrap().selected = true; 496 // Select second base device tree 497 registry.components_mut().nth(1).unwrap().selected = true; 498 499 assert!(registry.selected().is_err()); 500 } 501 502 #[test] test_components_autoselect()503 fn test_components_autoselect() { 504 let dt = include_bytes!("../../libfdt/test/data/base.dtb").to_vec(); 505 let mut buffer = vec![0u8; 2 * 1024 * 1024]; // 2 MB 506 let mut gbl_ops = FakeGblOps::new(&[]); 507 let mut registry = DeviceTreeComponentsRegistry::new(); 508 509 let sources = [ 510 DeviceTreeComponentSource::VendorBoot, 511 DeviceTreeComponentSource::Dtbo(Default::default()), 512 DeviceTreeComponentSource::Dtbo(Default::default()), 513 DeviceTreeComponentSource::Dtbo(Default::default()), 514 ]; 515 let mut current_buffer = &mut buffer[..]; 516 for source in sources.iter() { 517 current_buffer = registry.append(&mut gbl_ops, *source, &dt, current_buffer).unwrap(); 518 } 519 520 assert!(registry.autoselect().is_ok()); 521 522 // Expected auto selected data 523 let expected_selected = (registry.components().nth(0).unwrap().dt, &[][..]); 524 525 assert_eq!(registry.selected().unwrap(), expected_selected); 526 } 527 528 #[test] test_components_autoselect_no_overlays()529 fn test_components_autoselect_no_overlays() { 530 let dt = include_bytes!("../../libfdt/test/data/base.dtb").to_vec(); 531 let mut buffer = vec![0u8; 2 * 1024 * 1024]; // 2 MB 532 let mut gbl_ops = FakeGblOps::new(&[]); 533 let mut registry = DeviceTreeComponentsRegistry::new(); 534 535 registry 536 .append(&mut gbl_ops, DeviceTreeComponentSource::VendorBoot, &dt[..], &mut buffer) 537 .unwrap(); 538 539 assert!(registry.autoselect().is_ok()); 540 541 // Expected auto selected data 542 let expected_selected = (registry.components().nth(0).unwrap().dt, &[][..]); 543 544 assert_eq!(registry.selected().unwrap(), expected_selected); 545 } 546 547 #[test] test_components_autoselect_multiple_base_device_trees_failed()548 fn test_components_autoselect_multiple_base_device_trees_failed() { 549 let dt = include_bytes!("../../libfdt/test/data/base.dtb").to_vec(); 550 let mut buffer = vec![0u8; 2 * 1024 * 1024]; // 2 MB 551 let mut gbl_ops = FakeGblOps::new(&[]); 552 let mut registry = DeviceTreeComponentsRegistry::new(); 553 554 let mut current_buffer = &mut buffer[..]; 555 current_buffer = registry 556 .append(&mut gbl_ops, DeviceTreeComponentSource::VendorBoot, &dt[..], current_buffer) 557 .unwrap(); 558 registry 559 .append(&mut gbl_ops, DeviceTreeComponentSource::Boot, &dt[..], current_buffer) 560 .unwrap(); 561 562 assert!(registry.autoselect().is_err()); 563 } 564 565 #[test] test_components_autoselect_no_base_device_trees_failed()566 fn test_components_autoselect_no_base_device_trees_failed() { 567 let dt = include_bytes!("../../libfdt/test/data/base.dtb").to_vec(); 568 let mut buffer = vec![0u8; 2 * 1024 * 1024]; // 2 MB 569 let mut gbl_ops = FakeGblOps::new(&[]); 570 let mut registry = DeviceTreeComponentsRegistry::new(); 571 572 registry 573 .append( 574 &mut gbl_ops, 575 DeviceTreeComponentSource::Dtbo(Default::default()), 576 &dt[..], 577 &mut buffer, 578 ) 579 .unwrap(); 580 581 assert!(registry.autoselect().is_err()); 582 } 583 584 #[test] test_components_append_from_multifd()585 fn test_components_append_from_multifd() { 586 let half = include_bytes!("../../libfdt/test/data/base.dtb").to_vec(); 587 let dt = [half.clone(), half].concat(); 588 let mut buffer = vec![0u8; 2 * 1024 * 1024]; // 2 MB 589 let mut gbl_ops = FakeGblOps::new(&[]); 590 let mut registry = DeviceTreeComponentsRegistry::new(); 591 592 registry 593 .append(&mut gbl_ops, DeviceTreeComponentSource::VendorBoot, &dt[..], &mut buffer) 594 .unwrap(); 595 596 assert_eq!(registry.components().count(), 2); 597 } 598 } 599