1*5225e6b1SAndroid Build Coastguard Worker // Copyright 2023, 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 //! Module for constructing bootconfig. See the following for more details: 16*5225e6b1SAndroid Build Coastguard Worker //! 17*5225e6b1SAndroid Build Coastguard Worker //! https://source.android.com/docs/core/architecture/bootloader/implementing-bootconfig#bootloader-changes 18*5225e6b1SAndroid Build Coastguard Worker 19*5225e6b1SAndroid Build Coastguard Worker use liberror::{Error, Result}; 20*5225e6b1SAndroid Build Coastguard Worker 21*5225e6b1SAndroid Build Coastguard Worker /// A class for constructing bootconfig section. 22*5225e6b1SAndroid Build Coastguard Worker pub struct BootConfigBuilder<'a> { 23*5225e6b1SAndroid Build Coastguard Worker current_size: usize, 24*5225e6b1SAndroid Build Coastguard Worker buffer: &'a mut [u8], 25*5225e6b1SAndroid Build Coastguard Worker } 26*5225e6b1SAndroid Build Coastguard Worker 27*5225e6b1SAndroid Build Coastguard Worker const BOOTCONFIG_MAGIC: &str = "#BOOTCONFIG\n"; 28*5225e6b1SAndroid Build Coastguard Worker // Trailer structure: 29*5225e6b1SAndroid Build Coastguard Worker // struct { 30*5225e6b1SAndroid Build Coastguard Worker // config_size: u32, 31*5225e6b1SAndroid Build Coastguard Worker // checksum: u32, 32*5225e6b1SAndroid Build Coastguard Worker // bootconfig_magic: [u8] 33*5225e6b1SAndroid Build Coastguard Worker // } 34*5225e6b1SAndroid Build Coastguard Worker const BOOTCONFIG_TRAILER_SIZE: usize = 4 + 4 + BOOTCONFIG_MAGIC.len(); 35*5225e6b1SAndroid Build Coastguard Worker 36*5225e6b1SAndroid Build Coastguard Worker impl<'a> BootConfigBuilder<'a> { 37*5225e6b1SAndroid Build Coastguard Worker /// Initialize with a given buffer. new(buffer: &'a mut [u8]) -> Result<Self>38*5225e6b1SAndroid Build Coastguard Worker pub fn new(buffer: &'a mut [u8]) -> Result<Self> { 39*5225e6b1SAndroid Build Coastguard Worker if buffer.len() < BOOTCONFIG_TRAILER_SIZE { 40*5225e6b1SAndroid Build Coastguard Worker return Err(Error::BufferTooSmall(Some(BOOTCONFIG_TRAILER_SIZE))); 41*5225e6b1SAndroid Build Coastguard Worker } 42*5225e6b1SAndroid Build Coastguard Worker let mut ret = Self { current_size: 0, buffer: buffer }; 43*5225e6b1SAndroid Build Coastguard Worker ret.update_trailer()?; 44*5225e6b1SAndroid Build Coastguard Worker Ok(ret) 45*5225e6b1SAndroid Build Coastguard Worker } 46*5225e6b1SAndroid Build Coastguard Worker 47*5225e6b1SAndroid Build Coastguard Worker /// Get the remaining capacity for adding new bootconfig. remaining_capacity(&self) -> usize48*5225e6b1SAndroid Build Coastguard Worker pub fn remaining_capacity(&self) -> usize { 49*5225e6b1SAndroid Build Coastguard Worker self.buffer 50*5225e6b1SAndroid Build Coastguard Worker .len() 51*5225e6b1SAndroid Build Coastguard Worker .checked_sub(self.current_size) 52*5225e6b1SAndroid Build Coastguard Worker .unwrap() 53*5225e6b1SAndroid Build Coastguard Worker .checked_sub(BOOTCONFIG_TRAILER_SIZE) 54*5225e6b1SAndroid Build Coastguard Worker .unwrap() 55*5225e6b1SAndroid Build Coastguard Worker } 56*5225e6b1SAndroid Build Coastguard Worker 57*5225e6b1SAndroid Build Coastguard Worker /// Get the whole config bytes including trailer. config_bytes(&self) -> &[u8]58*5225e6b1SAndroid Build Coastguard Worker pub fn config_bytes(&self) -> &[u8] { 59*5225e6b1SAndroid Build Coastguard Worker // Arithmetic not expected to fail. 60*5225e6b1SAndroid Build Coastguard Worker &self.buffer[..self.current_size.checked_add(BOOTCONFIG_TRAILER_SIZE).unwrap()] 61*5225e6b1SAndroid Build Coastguard Worker } 62*5225e6b1SAndroid Build Coastguard Worker 63*5225e6b1SAndroid Build Coastguard Worker /// Append a new config via a reader callback. 64*5225e6b1SAndroid Build Coastguard Worker /// 65*5225e6b1SAndroid Build Coastguard Worker /// A `&mut [u8]` that covers the remaining space is passed to the callback for reading the 66*5225e6b1SAndroid Build Coastguard Worker /// config bytes. It should return the total size read if operation is successful or 67*5225e6b1SAndroid Build Coastguard Worker /// `Error::BufferTooSmall(Some(<minimum_buffer_size>))`. Attempting to return a size 68*5225e6b1SAndroid Build Coastguard Worker /// greater than the input will cause it to panic. Empty read is allowed. It's up to the caller 69*5225e6b1SAndroid Build Coastguard Worker /// to make sure the read content will eventually form a valid boot config. The API is for 70*5225e6b1SAndroid Build Coastguard Worker /// situations where configs are read from sources such as disk and separate buffer allocation 71*5225e6b1SAndroid Build Coastguard Worker /// is not possible or desired. add_with<F>(&mut self, reader: F) -> Result<()> where F: FnOnce(&[u8], &mut [u8]) -> Result<usize>,72*5225e6b1SAndroid Build Coastguard Worker pub fn add_with<F>(&mut self, reader: F) -> Result<()> 73*5225e6b1SAndroid Build Coastguard Worker where 74*5225e6b1SAndroid Build Coastguard Worker F: FnOnce(&[u8], &mut [u8]) -> Result<usize>, 75*5225e6b1SAndroid Build Coastguard Worker { 76*5225e6b1SAndroid Build Coastguard Worker let remains = self.remaining_capacity(); 77*5225e6b1SAndroid Build Coastguard Worker let (current_buffer, remains_buffer) = self.buffer.split_at_mut(self.current_size); 78*5225e6b1SAndroid Build Coastguard Worker let size = reader(¤t_buffer[..], &mut remains_buffer[..remains])?; 79*5225e6b1SAndroid Build Coastguard Worker assert!(size <= remains); 80*5225e6b1SAndroid Build Coastguard Worker self.current_size += size; 81*5225e6b1SAndroid Build Coastguard Worker // Content may have been modified. Re-compute trailer. 82*5225e6b1SAndroid Build Coastguard Worker self.update_trailer() 83*5225e6b1SAndroid Build Coastguard Worker } 84*5225e6b1SAndroid Build Coastguard Worker 85*5225e6b1SAndroid Build Coastguard Worker /// Append a new config from string. add(&mut self, config: &str) -> Result<()>86*5225e6b1SAndroid Build Coastguard Worker pub fn add(&mut self, config: &str) -> Result<()> { 87*5225e6b1SAndroid Build Coastguard Worker if self.remaining_capacity() < config.len() { 88*5225e6b1SAndroid Build Coastguard Worker return Err(Error::BufferTooSmall(Some(config.len()))); 89*5225e6b1SAndroid Build Coastguard Worker } 90*5225e6b1SAndroid Build Coastguard Worker self.add_with(|_, out| { 91*5225e6b1SAndroid Build Coastguard Worker out[..config.len()].clone_from_slice(config.as_bytes()); 92*5225e6b1SAndroid Build Coastguard Worker Ok(config.len()) 93*5225e6b1SAndroid Build Coastguard Worker }) 94*5225e6b1SAndroid Build Coastguard Worker } 95*5225e6b1SAndroid Build Coastguard Worker 96*5225e6b1SAndroid Build Coastguard Worker /// Update the boot config trailer at the end of parameter list. 97*5225e6b1SAndroid Build Coastguard Worker /// See specification at: 98*5225e6b1SAndroid Build Coastguard Worker /// https://source.android.com/docs/core/architecture/bootloader/implementing-bootconfig#bootloader-changes update_trailer(&mut self) -> Result<()>99*5225e6b1SAndroid Build Coastguard Worker fn update_trailer(&mut self) -> Result<()> { 100*5225e6b1SAndroid Build Coastguard Worker // Config size 101*5225e6b1SAndroid Build Coastguard Worker let size: u32 = self.current_size.try_into().or(Err(Error::Other(None)))?; 102*5225e6b1SAndroid Build Coastguard Worker // Check sum. 103*5225e6b1SAndroid Build Coastguard Worker let checksum = self.checksum(); 104*5225e6b1SAndroid Build Coastguard Worker let trailer = &mut self.buffer[self.current_size..]; 105*5225e6b1SAndroid Build Coastguard Worker trailer[..4].clone_from_slice(&size.to_le_bytes()); 106*5225e6b1SAndroid Build Coastguard Worker trailer[4..8].clone_from_slice(&checksum.to_le_bytes()); 107*5225e6b1SAndroid Build Coastguard Worker trailer[8..][..BOOTCONFIG_MAGIC.len()].clone_from_slice(BOOTCONFIG_MAGIC.as_bytes()); 108*5225e6b1SAndroid Build Coastguard Worker Ok(()) 109*5225e6b1SAndroid Build Coastguard Worker } 110*5225e6b1SAndroid Build Coastguard Worker 111*5225e6b1SAndroid Build Coastguard Worker /// Compute the checksum value. checksum(&self) -> u32112*5225e6b1SAndroid Build Coastguard Worker fn checksum(&self) -> u32 { 113*5225e6b1SAndroid Build Coastguard Worker self.buffer[..self.current_size] 114*5225e6b1SAndroid Build Coastguard Worker .iter() 115*5225e6b1SAndroid Build Coastguard Worker .map(|v| *v as u32) 116*5225e6b1SAndroid Build Coastguard Worker .reduce(|acc, v| acc.overflowing_add(v).0) 117*5225e6b1SAndroid Build Coastguard Worker .unwrap_or(0) 118*5225e6b1SAndroid Build Coastguard Worker } 119*5225e6b1SAndroid Build Coastguard Worker } 120*5225e6b1SAndroid Build Coastguard Worker 121*5225e6b1SAndroid Build Coastguard Worker impl core::fmt::Display for BootConfigBuilder<'_> { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result122*5225e6b1SAndroid Build Coastguard Worker fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 123*5225e6b1SAndroid Build Coastguard Worker let bytes = self.config_bytes(); 124*5225e6b1SAndroid Build Coastguard Worker for val in &bytes[..bytes.len().checked_sub(BOOTCONFIG_TRAILER_SIZE).unwrap()] { 125*5225e6b1SAndroid Build Coastguard Worker write!(f, "{}", core::ascii::escape_default(*val))?; 126*5225e6b1SAndroid Build Coastguard Worker } 127*5225e6b1SAndroid Build Coastguard Worker Ok(()) 128*5225e6b1SAndroid Build Coastguard Worker } 129*5225e6b1SAndroid Build Coastguard Worker } 130*5225e6b1SAndroid Build Coastguard Worker 131*5225e6b1SAndroid Build Coastguard Worker impl core::fmt::Write for BootConfigBuilder<'_> { write_str(&mut self, s: &str) -> core::fmt::Result132*5225e6b1SAndroid Build Coastguard Worker fn write_str(&mut self, s: &str) -> core::fmt::Result { 133*5225e6b1SAndroid Build Coastguard Worker self.add_with(|_, out| { 134*5225e6b1SAndroid Build Coastguard Worker out.get_mut(..s.len()) 135*5225e6b1SAndroid Build Coastguard Worker .ok_or(Error::BufferTooSmall(Some(s.len())))? 136*5225e6b1SAndroid Build Coastguard Worker .clone_from_slice(s.as_bytes()); 137*5225e6b1SAndroid Build Coastguard Worker Ok(s.len()) 138*5225e6b1SAndroid Build Coastguard Worker }) 139*5225e6b1SAndroid Build Coastguard Worker .map_err(|_| core::fmt::Error)?; 140*5225e6b1SAndroid Build Coastguard Worker Ok(()) 141*5225e6b1SAndroid Build Coastguard Worker } 142*5225e6b1SAndroid Build Coastguard Worker } 143*5225e6b1SAndroid Build Coastguard Worker 144*5225e6b1SAndroid Build Coastguard Worker #[cfg(test)] 145*5225e6b1SAndroid Build Coastguard Worker mod test { 146*5225e6b1SAndroid Build Coastguard Worker use super::*; 147*5225e6b1SAndroid Build Coastguard Worker use core::fmt::Write; 148*5225e6b1SAndroid Build Coastguard Worker 149*5225e6b1SAndroid Build Coastguard Worker // Taken from Cuttlefish on QEMU aarch64. 150*5225e6b1SAndroid Build Coastguard Worker const TEST_CONFIG: &str = "androidboot.hardware=cutf_cvm 151*5225e6b1SAndroid Build Coastguard Worker kernel.mac80211_hwsim.radios=0 152*5225e6b1SAndroid Build Coastguard Worker kernel.vmw_vsock_virtio_transport_common.virtio_transport_max_vsock_pkt_buf_size=16384 153*5225e6b1SAndroid Build Coastguard Worker androidboot.vendor.apex.com.google.emulated.camera.provider.hal=com.google.emulated.camera.provider.hal 154*5225e6b1SAndroid Build Coastguard Worker androidboot.slot_suffix=_a 155*5225e6b1SAndroid Build Coastguard Worker androidboot.force_normal_boot=1 156*5225e6b1SAndroid Build Coastguard Worker androidboot.hw_timeout_multiplier=50 157*5225e6b1SAndroid Build Coastguard Worker androidboot.fstab_suffix=cf.f2fs.hctr2 158*5225e6b1SAndroid Build Coastguard Worker androidboot.hypervisor.protected_vm.supported=0 159*5225e6b1SAndroid Build Coastguard Worker androidboot.modem_simulator_ports=9600 160*5225e6b1SAndroid Build Coastguard Worker androidboot.vsock_lights_port=6900 161*5225e6b1SAndroid Build Coastguard Worker androidboot.lcd_density=320 162*5225e6b1SAndroid Build Coastguard Worker androidboot.vendor.audiocontrol.server.port=9410 163*5225e6b1SAndroid Build Coastguard Worker androidboot.vendor.audiocontrol.server.cid=3 164*5225e6b1SAndroid Build Coastguard Worker androidboot.cuttlefish_config_server_port=6800 165*5225e6b1SAndroid Build Coastguard Worker androidboot.hardware.gralloc=minigbm 166*5225e6b1SAndroid Build Coastguard Worker androidboot.vsock_lights_cid=3 167*5225e6b1SAndroid Build Coastguard Worker androidboot.enable_confirmationui=0 168*5225e6b1SAndroid Build Coastguard Worker androidboot.hypervisor.vm.supported=0 169*5225e6b1SAndroid Build Coastguard Worker androidboot.setupwizard_mode=DISABLED 170*5225e6b1SAndroid Build Coastguard Worker androidboot.serialno=CUTTLEFISHCVD011 171*5225e6b1SAndroid Build Coastguard Worker androidboot.enable_bootanimation=1 172*5225e6b1SAndroid Build Coastguard Worker androidboot.hardware.hwcomposer.display_finder_mode=drm 173*5225e6b1SAndroid Build Coastguard Worker androidboot.hardware.angle_feature_overrides_enabled=preferLinearFilterForYUV:mapUnspecifiedColorSpaceToPassThrough 174*5225e6b1SAndroid Build Coastguard Worker androidboot.hardware.egl=mesa 175*5225e6b1SAndroid Build Coastguard Worker androidboot.boot_devices=4010000000.pcie 176*5225e6b1SAndroid Build Coastguard Worker androidboot.opengles.version=196608 177*5225e6b1SAndroid Build Coastguard Worker androidboot.wifi_mac_prefix=5554 178*5225e6b1SAndroid Build Coastguard Worker androidboot.vsock_tombstone_port=6600 179*5225e6b1SAndroid Build Coastguard Worker androidboot.hardware.hwcomposer=ranchu 180*5225e6b1SAndroid Build Coastguard Worker androidboot.hardware.hwcomposer.mode=client 181*5225e6b1SAndroid Build Coastguard Worker androidboot.console=ttyAMA0 182*5225e6b1SAndroid Build Coastguard Worker androidboot.ddr_size=4915MB 183*5225e6b1SAndroid Build Coastguard Worker androidboot.cpuvulkan.version=0 184*5225e6b1SAndroid Build Coastguard Worker androidboot.serialconsole=1 185*5225e6b1SAndroid Build Coastguard Worker androidboot.vbmeta.device=PARTUUID=2b7e273a-42a1-654b-bbad-8cb6ab2b6911 186*5225e6b1SAndroid Build Coastguard Worker androidboot.vbmeta.avb_version=1.1 187*5225e6b1SAndroid Build Coastguard Worker androidboot.vbmeta.device_state=unlocked 188*5225e6b1SAndroid Build Coastguard Worker androidboot.vbmeta.hash_alg=sha256 189*5225e6b1SAndroid Build Coastguard Worker androidboot.vbmeta.size=23040 190*5225e6b1SAndroid Build Coastguard Worker androidboot.vbmeta.digest=6d6cdbad779475dd945ed79e6bd79c0574541d34ff488fa5aeeb024d739dd0d2 191*5225e6b1SAndroid Build Coastguard Worker androidboot.vbmeta.invalidate_on_error=yes 192*5225e6b1SAndroid Build Coastguard Worker androidboot.veritymode=enforcing 193*5225e6b1SAndroid Build Coastguard Worker androidboot.verifiedbootstate=orange 194*5225e6b1SAndroid Build Coastguard Worker "; 195*5225e6b1SAndroid Build Coastguard Worker 196*5225e6b1SAndroid Build Coastguard Worker const TEST_CONFIG_TRAILER: &[u8; BOOTCONFIG_TRAILER_SIZE] = 197*5225e6b1SAndroid Build Coastguard Worker b"i\x07\x00\x00\xf9\xc4\x02\x00#BOOTCONFIG\n"; 198*5225e6b1SAndroid Build Coastguard Worker 199*5225e6b1SAndroid Build Coastguard Worker #[test] test_add()200*5225e6b1SAndroid Build Coastguard Worker fn test_add() { 201*5225e6b1SAndroid Build Coastguard Worker let mut buffer = [0u8; TEST_CONFIG.len() + TEST_CONFIG_TRAILER.len()]; 202*5225e6b1SAndroid Build Coastguard Worker let mut builder = BootConfigBuilder::new(&mut buffer[..]).unwrap(); 203*5225e6b1SAndroid Build Coastguard Worker builder.add(TEST_CONFIG).unwrap(); 204*5225e6b1SAndroid Build Coastguard Worker assert_eq!( 205*5225e6b1SAndroid Build Coastguard Worker builder.config_bytes().to_vec(), 206*5225e6b1SAndroid Build Coastguard Worker [TEST_CONFIG.as_bytes(), TEST_CONFIG_TRAILER].concat().to_vec() 207*5225e6b1SAndroid Build Coastguard Worker ); 208*5225e6b1SAndroid Build Coastguard Worker } 209*5225e6b1SAndroid Build Coastguard Worker 210*5225e6b1SAndroid Build Coastguard Worker #[test] test_add_incremental()211*5225e6b1SAndroid Build Coastguard Worker fn test_add_incremental() { 212*5225e6b1SAndroid Build Coastguard Worker let mut buffer = [0u8; TEST_CONFIG.len() + TEST_CONFIG_TRAILER.len()]; 213*5225e6b1SAndroid Build Coastguard Worker let mut builder = BootConfigBuilder::new(&mut buffer[..]).unwrap(); 214*5225e6b1SAndroid Build Coastguard Worker for ele in TEST_CONFIG.strip_suffix('\n').unwrap().split('\n') { 215*5225e6b1SAndroid Build Coastguard Worker let config = std::string::String::from(ele) + "\n"; 216*5225e6b1SAndroid Build Coastguard Worker builder.add(config.as_str()).unwrap(); 217*5225e6b1SAndroid Build Coastguard Worker } 218*5225e6b1SAndroid Build Coastguard Worker assert_eq!( 219*5225e6b1SAndroid Build Coastguard Worker builder.config_bytes().to_vec(), 220*5225e6b1SAndroid Build Coastguard Worker [TEST_CONFIG.as_bytes(), TEST_CONFIG_TRAILER].concat().to_vec() 221*5225e6b1SAndroid Build Coastguard Worker ); 222*5225e6b1SAndroid Build Coastguard Worker } 223*5225e6b1SAndroid Build Coastguard Worker 224*5225e6b1SAndroid Build Coastguard Worker #[test] test_add_with_incremental()225*5225e6b1SAndroid Build Coastguard Worker fn test_add_with_incremental() { 226*5225e6b1SAndroid Build Coastguard Worker let mut buffer = [0u8; TEST_CONFIG.len() + TEST_CONFIG_TRAILER.len()]; 227*5225e6b1SAndroid Build Coastguard Worker let mut builder = BootConfigBuilder::new(&mut buffer[..]).unwrap(); 228*5225e6b1SAndroid Build Coastguard Worker 229*5225e6b1SAndroid Build Coastguard Worker let mut offset = 0; 230*5225e6b1SAndroid Build Coastguard Worker for ele in TEST_CONFIG.strip_suffix('\n').unwrap().split('\n') { 231*5225e6b1SAndroid Build Coastguard Worker let config = std::string::String::from(ele) + "\n"; 232*5225e6b1SAndroid Build Coastguard Worker 233*5225e6b1SAndroid Build Coastguard Worker builder 234*5225e6b1SAndroid Build Coastguard Worker .add_with(|current, out| { 235*5225e6b1SAndroid Build Coastguard Worker assert_eq!(current, &TEST_CONFIG.as_bytes()[..offset]); 236*5225e6b1SAndroid Build Coastguard Worker 237*5225e6b1SAndroid Build Coastguard Worker out[..config.len()].copy_from_slice(config.as_bytes()); 238*5225e6b1SAndroid Build Coastguard Worker Ok(config.len()) 239*5225e6b1SAndroid Build Coastguard Worker }) 240*5225e6b1SAndroid Build Coastguard Worker .unwrap(); 241*5225e6b1SAndroid Build Coastguard Worker 242*5225e6b1SAndroid Build Coastguard Worker offset += config.len(); 243*5225e6b1SAndroid Build Coastguard Worker } 244*5225e6b1SAndroid Build Coastguard Worker assert_eq!( 245*5225e6b1SAndroid Build Coastguard Worker builder.config_bytes().to_vec(), 246*5225e6b1SAndroid Build Coastguard Worker [TEST_CONFIG.as_bytes(), TEST_CONFIG_TRAILER].concat().to_vec() 247*5225e6b1SAndroid Build Coastguard Worker ); 248*5225e6b1SAndroid Build Coastguard Worker } 249*5225e6b1SAndroid Build Coastguard Worker 250*5225e6b1SAndroid Build Coastguard Worker #[test] test_add_incremental_via_fmt_write()251*5225e6b1SAndroid Build Coastguard Worker fn test_add_incremental_via_fmt_write() { 252*5225e6b1SAndroid Build Coastguard Worker let mut buffer = [0u8; TEST_CONFIG.len() + TEST_CONFIG_TRAILER.len()]; 253*5225e6b1SAndroid Build Coastguard Worker let mut builder = BootConfigBuilder::new(&mut buffer[..]).unwrap(); 254*5225e6b1SAndroid Build Coastguard Worker for ele in TEST_CONFIG.strip_suffix('\n').unwrap().split('\n') { 255*5225e6b1SAndroid Build Coastguard Worker write!(builder, "{}\n", ele).unwrap(); 256*5225e6b1SAndroid Build Coastguard Worker } 257*5225e6b1SAndroid Build Coastguard Worker assert_eq!( 258*5225e6b1SAndroid Build Coastguard Worker builder.config_bytes().to_vec(), 259*5225e6b1SAndroid Build Coastguard Worker [TEST_CONFIG.as_bytes(), TEST_CONFIG_TRAILER].concat().to_vec() 260*5225e6b1SAndroid Build Coastguard Worker ); 261*5225e6b1SAndroid Build Coastguard Worker } 262*5225e6b1SAndroid Build Coastguard Worker 263*5225e6b1SAndroid Build Coastguard Worker #[test] test_new_buffer_too_small()264*5225e6b1SAndroid Build Coastguard Worker fn test_new_buffer_too_small() { 265*5225e6b1SAndroid Build Coastguard Worker let mut buffer = [0u8; BOOTCONFIG_TRAILER_SIZE - 1]; 266*5225e6b1SAndroid Build Coastguard Worker assert!(BootConfigBuilder::new(&mut buffer[..]).is_err()); 267*5225e6b1SAndroid Build Coastguard Worker } 268*5225e6b1SAndroid Build Coastguard Worker 269*5225e6b1SAndroid Build Coastguard Worker #[test] test_add_buffer_too_small()270*5225e6b1SAndroid Build Coastguard Worker fn test_add_buffer_too_small() { 271*5225e6b1SAndroid Build Coastguard Worker let mut buffer = [0u8; BOOTCONFIG_TRAILER_SIZE + 1]; 272*5225e6b1SAndroid Build Coastguard Worker let mut builder = BootConfigBuilder::new(&mut buffer[..]).unwrap(); 273*5225e6b1SAndroid Build Coastguard Worker assert!(builder.add("a\n").is_err()); 274*5225e6b1SAndroid Build Coastguard Worker } 275*5225e6b1SAndroid Build Coastguard Worker 276*5225e6b1SAndroid Build Coastguard Worker #[test] test_add_empty_string()277*5225e6b1SAndroid Build Coastguard Worker fn test_add_empty_string() { 278*5225e6b1SAndroid Build Coastguard Worker let mut buffer = [0u8; BOOTCONFIG_TRAILER_SIZE + 1]; 279*5225e6b1SAndroid Build Coastguard Worker let mut builder = BootConfigBuilder::new(&mut buffer[..]).unwrap(); 280*5225e6b1SAndroid Build Coastguard Worker builder.add("").unwrap(); 281*5225e6b1SAndroid Build Coastguard Worker } 282*5225e6b1SAndroid Build Coastguard Worker 283*5225e6b1SAndroid Build Coastguard Worker #[test] test_add_with_error()284*5225e6b1SAndroid Build Coastguard Worker fn test_add_with_error() { 285*5225e6b1SAndroid Build Coastguard Worker let mut buffer = [0u8; BOOTCONFIG_TRAILER_SIZE + 1]; 286*5225e6b1SAndroid Build Coastguard Worker let mut builder = BootConfigBuilder::new(&mut buffer[..]).unwrap(); 287*5225e6b1SAndroid Build Coastguard Worker assert!(builder.add_with(|_, _| Err(Error::Other(None))).is_err()); 288*5225e6b1SAndroid Build Coastguard Worker } 289*5225e6b1SAndroid Build Coastguard Worker } 290