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