1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 The ChromiumOS Authors 2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file. 4*bb4ee6a4SAndroid Build Coastguard Worker 5*bb4ee6a4SAndroid Build Coastguard Worker //! fw_cfg device implementing QEMU's Firmware Configuration interface 6*bb4ee6a4SAndroid Build Coastguard Worker //! <https://www.qemu.org/docs/master/specs/fw_cfg.html> 7*bb4ee6a4SAndroid Build Coastguard Worker 8*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::HashSet; 9*bb4ee6a4SAndroid Build Coastguard Worker use std::fs; 10*bb4ee6a4SAndroid Build Coastguard Worker use std::iter::repeat; 11*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf; 12*bb4ee6a4SAndroid Build Coastguard Worker 13*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] 14*bb4ee6a4SAndroid Build Coastguard Worker use base::error; 15*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize; 16*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize; 17*bb4ee6a4SAndroid Build Coastguard Worker use serde_keyvalue::FromKeyValues; 18*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error as ThisError; 19*bb4ee6a4SAndroid Build Coastguard Worker 20*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusAccessInfo; 21*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusDevice; 22*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceId; 23*bb4ee6a4SAndroid Build Coastguard Worker use crate::Suspendable; 24*bb4ee6a4SAndroid Build Coastguard Worker 25*bb4ee6a4SAndroid Build Coastguard Worker pub const FW_CFG_BASE_PORT: u64 = 0x510; 26*bb4ee6a4SAndroid Build Coastguard Worker pub const FW_CFG_WIDTH: u64 = 0x4; 27*bb4ee6a4SAndroid Build Coastguard Worker // For the 16-bit selector, the 2nd highest-order bit represents whether the data port will be read 28*bb4ee6a4SAndroid Build Coastguard Worker // or written to. Because this has been deprecrated by Qemu, this bit is useless. The highest order 29*bb4ee6a4SAndroid Build Coastguard Worker // bit represents whether the selected configuration item is arch-specific. Therefore, only the 30*bb4ee6a4SAndroid Build Coastguard Worker // lower 14 bits are used for indexing and we mask the two highest bits off with 31*bb4ee6a4SAndroid Build Coastguard Worker // FW_CFG_SELECTOR_SELECT_MASK. 16384 = 2^14. 32*bb4ee6a4SAndroid Build Coastguard Worker pub const FW_CFG_MAX_FILE_SLOTS: usize = 16384 - FW_CFG_FILE_FIRST; 33*bb4ee6a4SAndroid Build Coastguard Worker const FW_CFG_FILE_FIRST: usize = 0x0020; 34*bb4ee6a4SAndroid Build Coastguard Worker const FW_CFG_SELECTOR_PORT_OFFSET: u64 = 0x0; 35*bb4ee6a4SAndroid Build Coastguard Worker const FW_CFG_DATA_PORT_OFFSET: u64 = 0x1; 36*bb4ee6a4SAndroid Build Coastguard Worker const FW_CFG_SELECTOR_RW_MASK: u16 = 0x2000; 37*bb4ee6a4SAndroid Build Coastguard Worker const FW_CFG_SELECTOR_ARCH_MASK: u16 = 0x4000; 38*bb4ee6a4SAndroid Build Coastguard Worker const FW_CFG_SELECTOR_SELECT_MASK: u16 = 0xbfff; 39*bb4ee6a4SAndroid Build Coastguard Worker const FW_CFG_SIGNATURE: [u8; 4] = [b'Q', b'E', b'M', b'U']; 40*bb4ee6a4SAndroid Build Coastguard Worker const FW_CFG_REVISION: [u8; 4] = [0, 0, 0, 1]; 41*bb4ee6a4SAndroid Build Coastguard Worker const FW_CFG_SIGNATURE_SELECTOR: u16 = 0x0000; 42*bb4ee6a4SAndroid Build Coastguard Worker const FW_CFG_REVISION_SELECTOR: u16 = 0x0001; 43*bb4ee6a4SAndroid Build Coastguard Worker const FW_CFG_FILE_DIR_SELECTOR: u16 = 0x0019; 44*bb4ee6a4SAndroid Build Coastguard Worker // Code that uses fw_cfg expects to read a char[56] for filenames 45*bb4ee6a4SAndroid Build Coastguard Worker const FW_CFG_FILENAME_SIZE: usize = 56; 46*bb4ee6a4SAndroid Build Coastguard Worker 47*bb4ee6a4SAndroid Build Coastguard Worker #[derive(ThisError, Debug)] 48*bb4ee6a4SAndroid Build Coastguard Worker pub enum Error { 49*bb4ee6a4SAndroid Build Coastguard Worker #[error("Ran out of file slots")] 50*bb4ee6a4SAndroid Build Coastguard Worker InsufficientFileSlots, 51*bb4ee6a4SAndroid Build Coastguard Worker 52*bb4ee6a4SAndroid Build Coastguard Worker #[error("File already exists")] 53*bb4ee6a4SAndroid Build Coastguard Worker FileAlreadyExists, 54*bb4ee6a4SAndroid Build Coastguard Worker 55*bb4ee6a4SAndroid Build Coastguard Worker #[error("Data blob's size too large: overflowed u32")] 56*bb4ee6a4SAndroid Build Coastguard Worker SizeOverflow, 57*bb4ee6a4SAndroid Build Coastguard Worker 58*bb4ee6a4SAndroid Build Coastguard Worker #[error("too many entries: oveflows u16 selector")] 59*bb4ee6a4SAndroid Build Coastguard Worker IndexOverflow, 60*bb4ee6a4SAndroid Build Coastguard Worker 61*bb4ee6a4SAndroid Build Coastguard Worker #[error("Filename must be less than 55 characters long")] 62*bb4ee6a4SAndroid Build Coastguard Worker FileNameTooLong, 63*bb4ee6a4SAndroid Build Coastguard Worker 64*bb4ee6a4SAndroid Build Coastguard Worker #[error("Unable to open file {0} for fw_cfg: {1}")] 65*bb4ee6a4SAndroid Build Coastguard Worker FileOpen(PathBuf, std::io::Error), 66*bb4ee6a4SAndroid Build Coastguard Worker 67*bb4ee6a4SAndroid Build Coastguard Worker #[error("fw_cfg parameters must have exactly one of string or path")] 68*bb4ee6a4SAndroid Build Coastguard Worker StringOrPathRequired, 69*bb4ee6a4SAndroid Build Coastguard Worker } 70*bb4ee6a4SAndroid Build Coastguard Worker 71*bb4ee6a4SAndroid Build Coastguard Worker pub type Result<T> = std::result::Result<T, Error>; 72*bb4ee6a4SAndroid Build Coastguard Worker 73*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Debug, Deserialize, Serialize, FromKeyValues, PartialEq, Eq)] 74*bb4ee6a4SAndroid Build Coastguard Worker #[serde(deny_unknown_fields, rename_all = "kebab-case")] 75*bb4ee6a4SAndroid Build Coastguard Worker pub struct FwCfgParameters { 76*bb4ee6a4SAndroid Build Coastguard Worker pub name: String, 77*bb4ee6a4SAndroid Build Coastguard Worker pub string: Option<String>, 78*bb4ee6a4SAndroid Build Coastguard Worker pub path: Option<PathBuf>, 79*bb4ee6a4SAndroid Build Coastguard Worker } 80*bb4ee6a4SAndroid Build Coastguard Worker 81*bb4ee6a4SAndroid Build Coastguard Worker #[derive(PartialEq)] 82*bb4ee6a4SAndroid Build Coastguard Worker pub enum FwCfgItemType { 83*bb4ee6a4SAndroid Build Coastguard Worker GenericItem, 84*bb4ee6a4SAndroid Build Coastguard Worker ArchSpecificItem, 85*bb4ee6a4SAndroid Build Coastguard Worker FileDir, 86*bb4ee6a4SAndroid Build Coastguard Worker Signature, 87*bb4ee6a4SAndroid Build Coastguard Worker RevisionVector, 88*bb4ee6a4SAndroid Build Coastguard Worker } 89*bb4ee6a4SAndroid Build Coastguard Worker 90*bb4ee6a4SAndroid Build Coastguard Worker impl FwCfgItemType { value(&self) -> usize91*bb4ee6a4SAndroid Build Coastguard Worker fn value(&self) -> usize { 92*bb4ee6a4SAndroid Build Coastguard Worker match self { 93*bb4ee6a4SAndroid Build Coastguard Worker FwCfgItemType::ArchSpecificItem => 1, 94*bb4ee6a4SAndroid Build Coastguard Worker _ => 0, 95*bb4ee6a4SAndroid Build Coastguard Worker } 96*bb4ee6a4SAndroid Build Coastguard Worker } 97*bb4ee6a4SAndroid Build Coastguard Worker } 98*bb4ee6a4SAndroid Build Coastguard Worker 99*bb4ee6a4SAndroid Build Coastguard Worker // Contains metadata about the entries stored in fw_cfg. 100*bb4ee6a4SAndroid Build Coastguard Worker // FwCfgFile is exposed to the the guest 101*bb4ee6a4SAndroid Build Coastguard Worker // so that the guest may search for the entry 102*bb4ee6a4SAndroid Build Coastguard Worker // with the desired filename and obtain its 16-bit-wide select 103*bb4ee6a4SAndroid Build Coastguard Worker // key to write to the control register 104*bb4ee6a4SAndroid Build Coastguard Worker struct FwCfgFile { 105*bb4ee6a4SAndroid Build Coastguard Worker pub size: u32, 106*bb4ee6a4SAndroid Build Coastguard Worker pub select: u16, 107*bb4ee6a4SAndroid Build Coastguard Worker pub name: String, 108*bb4ee6a4SAndroid Build Coastguard Worker } 109*bb4ee6a4SAndroid Build Coastguard Worker 110*bb4ee6a4SAndroid Build Coastguard Worker // Contains the actual data. The data is represented as an 111*bb4ee6a4SAndroid Build Coastguard Worker // array of u8 to conviently pass 112*bb4ee6a4SAndroid Build Coastguard Worker // a data item byte-by-byte when read() is called 113*bb4ee6a4SAndroid Build Coastguard Worker // on that item 114*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)] 115*bb4ee6a4SAndroid Build Coastguard Worker struct FwCfgEntry { 116*bb4ee6a4SAndroid Build Coastguard Worker pub allow_write: bool, 117*bb4ee6a4SAndroid Build Coastguard Worker pub data: Vec<u8>, 118*bb4ee6a4SAndroid Build Coastguard Worker } 119*bb4ee6a4SAndroid Build Coastguard Worker 120*bb4ee6a4SAndroid Build Coastguard Worker // Device exposed to the rest of crosvm. Contains state information in addition to arrays of 121*bb4ee6a4SAndroid Build Coastguard Worker // FwCfgEntry and FwCfgFile. cur_entry keeps the index of the currently selected entry. cur_offset 122*bb4ee6a4SAndroid Build Coastguard Worker // keeps the byte offset within cur_entry. Storing cur_offset is neccessary because the data IO port 123*bb4ee6a4SAndroid Build Coastguard Worker // is only 8 bits wide, so a call to read() will only retrieve one 8 bit chunk of data at a time. 124*bb4ee6a4SAndroid Build Coastguard Worker // cur_offset allows for a data item larger than 8 bits to be read through multiple calls to read(), 125*bb4ee6a4SAndroid Build Coastguard Worker // maintaining the position of the current read and incrementing across calls to read(). 126*bb4ee6a4SAndroid Build Coastguard Worker pub struct FwCfgDevice { 127*bb4ee6a4SAndroid Build Coastguard Worker file_slots: usize, 128*bb4ee6a4SAndroid Build Coastguard Worker // entries[0] holds generic fw_cfg items in addition to special items (file dir, signature, and 129*bb4ee6a4SAndroid Build Coastguard Worker // revision vector). entries[1] holds arch-specific items. 130*bb4ee6a4SAndroid Build Coastguard Worker entries: [Vec<FwCfgEntry>; 2], 131*bb4ee6a4SAndroid Build Coastguard Worker files: Vec<FwCfgFile>, 132*bb4ee6a4SAndroid Build Coastguard Worker cur_item_type: FwCfgItemType, 133*bb4ee6a4SAndroid Build Coastguard Worker cur_entry: u16, 134*bb4ee6a4SAndroid Build Coastguard Worker cur_offset: usize, 135*bb4ee6a4SAndroid Build Coastguard Worker file_names: HashSet<String>, 136*bb4ee6a4SAndroid Build Coastguard Worker } 137*bb4ee6a4SAndroid Build Coastguard Worker 138*bb4ee6a4SAndroid Build Coastguard Worker impl FwCfgDevice { new(file_slots: usize, fw_cfg_parameters: Vec<FwCfgParameters>) -> Result<FwCfgDevice>139*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(file_slots: usize, fw_cfg_parameters: Vec<FwCfgParameters>) -> Result<FwCfgDevice> { 140*bb4ee6a4SAndroid Build Coastguard Worker let mut device = FwCfgDevice { 141*bb4ee6a4SAndroid Build Coastguard Worker file_slots, 142*bb4ee6a4SAndroid Build Coastguard Worker entries: [ 143*bb4ee6a4SAndroid Build Coastguard Worker vec![ 144*bb4ee6a4SAndroid Build Coastguard Worker FwCfgEntry { 145*bb4ee6a4SAndroid Build Coastguard Worker allow_write: false, 146*bb4ee6a4SAndroid Build Coastguard Worker data: vec![] 147*bb4ee6a4SAndroid Build Coastguard Worker }; 148*bb4ee6a4SAndroid Build Coastguard Worker FW_CFG_FILE_FIRST 149*bb4ee6a4SAndroid Build Coastguard Worker ], 150*bb4ee6a4SAndroid Build Coastguard Worker Vec::new(), 151*bb4ee6a4SAndroid Build Coastguard Worker ], 152*bb4ee6a4SAndroid Build Coastguard Worker files: Vec::new(), 153*bb4ee6a4SAndroid Build Coastguard Worker cur_item_type: FwCfgItemType::GenericItem, 154*bb4ee6a4SAndroid Build Coastguard Worker cur_entry: 0, 155*bb4ee6a4SAndroid Build Coastguard Worker cur_offset: 0, 156*bb4ee6a4SAndroid Build Coastguard Worker file_names: HashSet::new(), 157*bb4ee6a4SAndroid Build Coastguard Worker }; 158*bb4ee6a4SAndroid Build Coastguard Worker 159*bb4ee6a4SAndroid Build Coastguard Worker for param in fw_cfg_parameters { 160*bb4ee6a4SAndroid Build Coastguard Worker let data = match (¶m.string, ¶m.path) { 161*bb4ee6a4SAndroid Build Coastguard Worker (Some(string), None) => string.as_bytes().to_vec(), 162*bb4ee6a4SAndroid Build Coastguard Worker (None, Some(path)) => { 163*bb4ee6a4SAndroid Build Coastguard Worker fs::read(path).map_err(|e| Error::FileOpen(path.clone(), e))? 164*bb4ee6a4SAndroid Build Coastguard Worker } 165*bb4ee6a4SAndroid Build Coastguard Worker _ => return Err(Error::StringOrPathRequired), 166*bb4ee6a4SAndroid Build Coastguard Worker }; 167*bb4ee6a4SAndroid Build Coastguard Worker 168*bb4ee6a4SAndroid Build Coastguard Worker // The file added from the command line will be a generic item. QEMU does not 169*bb4ee6a4SAndroid Build Coastguard Worker // give users the option to specify whether the user-specified blob is 170*bb4ee6a4SAndroid Build Coastguard Worker // arch-specific, so we won't either. 171*bb4ee6a4SAndroid Build Coastguard Worker device.add_file(¶m.name, data, FwCfgItemType::GenericItem)? 172*bb4ee6a4SAndroid Build Coastguard Worker } 173*bb4ee6a4SAndroid Build Coastguard Worker 174*bb4ee6a4SAndroid Build Coastguard Worker device.add_bytes(FW_CFG_SIGNATURE.to_vec(), FwCfgItemType::Signature); 175*bb4ee6a4SAndroid Build Coastguard Worker device.add_bytes(FW_CFG_REVISION.to_vec(), FwCfgItemType::RevisionVector); 176*bb4ee6a4SAndroid Build Coastguard Worker 177*bb4ee6a4SAndroid Build Coastguard Worker Ok(device) 178*bb4ee6a4SAndroid Build Coastguard Worker } 179*bb4ee6a4SAndroid Build Coastguard Worker 180*bb4ee6a4SAndroid Build Coastguard Worker /// Adds a file to the device. 181*bb4ee6a4SAndroid Build Coastguard Worker /// 182*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments 183*bb4ee6a4SAndroid Build Coastguard Worker /// 184*bb4ee6a4SAndroid Build Coastguard Worker /// - `filename`: Name of file. Must be valid a Unix-style filename 185*bb4ee6a4SAndroid Build Coastguard Worker /// - `data`: File data as bytes add_file( &mut self, filename: &str, data: Vec<u8>, item_type: FwCfgItemType, ) -> Result<()>186*bb4ee6a4SAndroid Build Coastguard Worker pub fn add_file( 187*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 188*bb4ee6a4SAndroid Build Coastguard Worker filename: &str, 189*bb4ee6a4SAndroid Build Coastguard Worker data: Vec<u8>, 190*bb4ee6a4SAndroid Build Coastguard Worker item_type: FwCfgItemType, 191*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> { 192*bb4ee6a4SAndroid Build Coastguard Worker // Adds a data blob to the device under the name filename. This entails creating an 193*bb4ee6a4SAndroid Build Coastguard Worker // FwCfgEntry and its associated FwCfgFile and adding them to FwCfgDevice. 194*bb4ee6a4SAndroid Build Coastguard Worker 195*bb4ee6a4SAndroid Build Coastguard Worker if self.files.len() >= FW_CFG_MAX_FILE_SLOTS || self.files.len() >= self.file_slots { 196*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::InsufficientFileSlots); 197*bb4ee6a4SAndroid Build Coastguard Worker } 198*bb4ee6a4SAndroid Build Coastguard Worker 199*bb4ee6a4SAndroid Build Coastguard Worker if filename.len() > FW_CFG_FILENAME_SIZE - 1 { 200*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::FileNameTooLong); 201*bb4ee6a4SAndroid Build Coastguard Worker } 202*bb4ee6a4SAndroid Build Coastguard Worker 203*bb4ee6a4SAndroid Build Coastguard Worker // No need to worry about endianess in this function. We will deal with this in read(). We 204*bb4ee6a4SAndroid Build Coastguard Worker // are only using FwCfgFile internally. 205*bb4ee6a4SAndroid Build Coastguard Worker let index = self.entries[item_type.value()].len(); 206*bb4ee6a4SAndroid Build Coastguard Worker 207*bb4ee6a4SAndroid Build Coastguard Worker if self.file_names.contains(filename) { 208*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::FileAlreadyExists); 209*bb4ee6a4SAndroid Build Coastguard Worker } 210*bb4ee6a4SAndroid Build Coastguard Worker 211*bb4ee6a4SAndroid Build Coastguard Worker // Since the size field of an entry is stored as a u32, the largest file that can be stored 212*bb4ee6a4SAndroid Build Coastguard Worker // in the device is 2^32 - 1 ~ 4GB 213*bb4ee6a4SAndroid Build Coastguard Worker let size: u32 = data.len().try_into().map_err(|_| Error::SizeOverflow)?; 214*bb4ee6a4SAndroid Build Coastguard Worker 215*bb4ee6a4SAndroid Build Coastguard Worker let mut select: u16 = (index).try_into().map_err(|_| Error::IndexOverflow)?; 216*bb4ee6a4SAndroid Build Coastguard Worker 217*bb4ee6a4SAndroid Build Coastguard Worker if item_type == FwCfgItemType::ArchSpecificItem { 218*bb4ee6a4SAndroid Build Coastguard Worker select |= FW_CFG_SELECTOR_ARCH_MASK; 219*bb4ee6a4SAndroid Build Coastguard Worker } 220*bb4ee6a4SAndroid Build Coastguard Worker 221*bb4ee6a4SAndroid Build Coastguard Worker let new_file = FwCfgFile { 222*bb4ee6a4SAndroid Build Coastguard Worker size, 223*bb4ee6a4SAndroid Build Coastguard Worker select, 224*bb4ee6a4SAndroid Build Coastguard Worker name: filename.to_owned(), 225*bb4ee6a4SAndroid Build Coastguard Worker }; 226*bb4ee6a4SAndroid Build Coastguard Worker 227*bb4ee6a4SAndroid Build Coastguard Worker self.add_bytes(data, item_type); 228*bb4ee6a4SAndroid Build Coastguard Worker self.files.push(new_file); 229*bb4ee6a4SAndroid Build Coastguard Worker self.file_names.insert(filename.to_string()); 230*bb4ee6a4SAndroid Build Coastguard Worker // We need to update the file_dir entry every time we insert a new file. 231*bb4ee6a4SAndroid Build Coastguard Worker self.update_file_dir_entry(); 232*bb4ee6a4SAndroid Build Coastguard Worker 233*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 234*bb4ee6a4SAndroid Build Coastguard Worker } 235*bb4ee6a4SAndroid Build Coastguard Worker add_bytes(&mut self, data: Vec<u8>, item_type: FwCfgItemType)236*bb4ee6a4SAndroid Build Coastguard Worker fn add_bytes(&mut self, data: Vec<u8>, item_type: FwCfgItemType) { 237*bb4ee6a4SAndroid Build Coastguard Worker // Add a FwCfgEntry to FwCfgDevice's entries array 238*bb4ee6a4SAndroid Build Coastguard Worker 239*bb4ee6a4SAndroid Build Coastguard Worker let new_entry = FwCfgEntry { 240*bb4ee6a4SAndroid Build Coastguard Worker allow_write: false, 241*bb4ee6a4SAndroid Build Coastguard Worker data, 242*bb4ee6a4SAndroid Build Coastguard Worker }; 243*bb4ee6a4SAndroid Build Coastguard Worker 244*bb4ee6a4SAndroid Build Coastguard Worker match item_type { 245*bb4ee6a4SAndroid Build Coastguard Worker FwCfgItemType::GenericItem | FwCfgItemType::ArchSpecificItem => { 246*bb4ee6a4SAndroid Build Coastguard Worker self.entries[item_type.value()].push(new_entry) 247*bb4ee6a4SAndroid Build Coastguard Worker } 248*bb4ee6a4SAndroid Build Coastguard Worker FwCfgItemType::FileDir => { 249*bb4ee6a4SAndroid Build Coastguard Worker self.entries[item_type.value()][FW_CFG_FILE_DIR_SELECTOR as usize] = new_entry 250*bb4ee6a4SAndroid Build Coastguard Worker } 251*bb4ee6a4SAndroid Build Coastguard Worker FwCfgItemType::Signature => { 252*bb4ee6a4SAndroid Build Coastguard Worker self.entries[item_type.value()][FW_CFG_SIGNATURE_SELECTOR as usize] = new_entry 253*bb4ee6a4SAndroid Build Coastguard Worker } 254*bb4ee6a4SAndroid Build Coastguard Worker FwCfgItemType::RevisionVector => { 255*bb4ee6a4SAndroid Build Coastguard Worker self.entries[item_type.value()][FW_CFG_REVISION_SELECTOR as usize] = new_entry 256*bb4ee6a4SAndroid Build Coastguard Worker } 257*bb4ee6a4SAndroid Build Coastguard Worker } 258*bb4ee6a4SAndroid Build Coastguard Worker } 259*bb4ee6a4SAndroid Build Coastguard Worker update_file_dir_entry(&mut self)260*bb4ee6a4SAndroid Build Coastguard Worker fn update_file_dir_entry(&mut self) { 261*bb4ee6a4SAndroid Build Coastguard Worker let mut raw_file_dir: Vec<u8> = Vec::new(); 262*bb4ee6a4SAndroid Build Coastguard Worker // casting to u32 should not be problematic. insert_file() assures that there can be no 263*bb4ee6a4SAndroid Build Coastguard Worker // more than 2^14 items in the device. 264*bb4ee6a4SAndroid Build Coastguard Worker let files_dir_count = self.files.len() as u32; 265*bb4ee6a4SAndroid Build Coastguard Worker raw_file_dir.extend_from_slice(&files_dir_count.to_be_bytes()); 266*bb4ee6a4SAndroid Build Coastguard Worker 267*bb4ee6a4SAndroid Build Coastguard Worker for file in &self.files { 268*bb4ee6a4SAndroid Build Coastguard Worker raw_file_dir.extend_from_slice(&file.size.to_be_bytes()); 269*bb4ee6a4SAndroid Build Coastguard Worker raw_file_dir.extend_from_slice(&file.select.to_be_bytes()); 270*bb4ee6a4SAndroid Build Coastguard Worker // The caller expects a "reserved" field to be present on each FwCfgFile. Since 271*bb4ee6a4SAndroid Build Coastguard Worker // we always set the field to zero, we don't bother to store it on FwCfgDevice and 272*bb4ee6a4SAndroid Build Coastguard Worker // return zero unconditionally. 273*bb4ee6a4SAndroid Build Coastguard Worker raw_file_dir.extend_from_slice(&[0, 0]); 274*bb4ee6a4SAndroid Build Coastguard Worker raw_file_dir.extend_from_slice(file.name.as_bytes()); 275*bb4ee6a4SAndroid Build Coastguard Worker // Padding for c-style char[] 276*bb4ee6a4SAndroid Build Coastguard Worker raw_file_dir.extend(repeat(0).take(FW_CFG_FILENAME_SIZE - file.name.as_bytes().len())); 277*bb4ee6a4SAndroid Build Coastguard Worker } 278*bb4ee6a4SAndroid Build Coastguard Worker 279*bb4ee6a4SAndroid Build Coastguard Worker self.add_bytes(raw_file_dir, FwCfgItemType::FileDir); 280*bb4ee6a4SAndroid Build Coastguard Worker } 281*bb4ee6a4SAndroid Build Coastguard Worker } 282*bb4ee6a4SAndroid Build Coastguard Worker 283*bb4ee6a4SAndroid Build Coastguard Worker // We implement two 8-bit registers: a Selector(Control) Register and a Data Register 284*bb4ee6a4SAndroid Build Coastguard Worker impl BusDevice for FwCfgDevice { device_id(&self) -> DeviceId285*bb4ee6a4SAndroid Build Coastguard Worker fn device_id(&self) -> DeviceId { 286*bb4ee6a4SAndroid Build Coastguard Worker super::CrosvmDeviceId::FwCfg.into() 287*bb4ee6a4SAndroid Build Coastguard Worker } 288*bb4ee6a4SAndroid Build Coastguard Worker debug_label(&self) -> String289*bb4ee6a4SAndroid Build Coastguard Worker fn debug_label(&self) -> String { 290*bb4ee6a4SAndroid Build Coastguard Worker "FwCfg".to_owned() 291*bb4ee6a4SAndroid Build Coastguard Worker } 292*bb4ee6a4SAndroid Build Coastguard Worker 293*bb4ee6a4SAndroid Build Coastguard Worker // Read a byte from the FwCfgDevice. The byte read is based on the current state of the device. read(&mut self, info: BusAccessInfo, data: &mut [u8])294*bb4ee6a4SAndroid Build Coastguard Worker fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) { 295*bb4ee6a4SAndroid Build Coastguard Worker if data.len() != 1 { 296*bb4ee6a4SAndroid Build Coastguard Worker return; 297*bb4ee6a4SAndroid Build Coastguard Worker } 298*bb4ee6a4SAndroid Build Coastguard Worker 299*bb4ee6a4SAndroid Build Coastguard Worker // Attemping to read anything other than the data port is a NOP 300*bb4ee6a4SAndroid Build Coastguard Worker if info.offset == FW_CFG_DATA_PORT_OFFSET { 301*bb4ee6a4SAndroid Build Coastguard Worker let entries_index = self.cur_entry as usize; 302*bb4ee6a4SAndroid Build Coastguard Worker // If the caller attempts to read bytes past the current entry, read returns 303*bb4ee6a4SAndroid Build Coastguard Worker // zero 304*bb4ee6a4SAndroid Build Coastguard Worker if self.cur_offset 305*bb4ee6a4SAndroid Build Coastguard Worker >= self.entries[self.cur_item_type.value()][entries_index] 306*bb4ee6a4SAndroid Build Coastguard Worker .data 307*bb4ee6a4SAndroid Build Coastguard Worker .len() 308*bb4ee6a4SAndroid Build Coastguard Worker { 309*bb4ee6a4SAndroid Build Coastguard Worker data[0] = 0x00; 310*bb4ee6a4SAndroid Build Coastguard Worker return; 311*bb4ee6a4SAndroid Build Coastguard Worker } 312*bb4ee6a4SAndroid Build Coastguard Worker data[0] = self.entries[self.cur_item_type.value()][entries_index].data[self.cur_offset]; 313*bb4ee6a4SAndroid Build Coastguard Worker self.cur_offset += 1; 314*bb4ee6a4SAndroid Build Coastguard Worker } 315*bb4ee6a4SAndroid Build Coastguard Worker } 316*bb4ee6a4SAndroid Build Coastguard Worker 317*bb4ee6a4SAndroid Build Coastguard Worker // Write to the FwCfgDevice. Used to set the select register. write(&mut self, info: BusAccessInfo, data: &[u8])318*bb4ee6a4SAndroid Build Coastguard Worker fn write(&mut self, info: BusAccessInfo, data: &[u8]) { 319*bb4ee6a4SAndroid Build Coastguard Worker // Attempting to write to any port other than the data port is a NOP 320*bb4ee6a4SAndroid Build Coastguard Worker if info.offset == FW_CFG_SELECTOR_PORT_OFFSET { 321*bb4ee6a4SAndroid Build Coastguard Worker if data.len() != 2 { 322*bb4ee6a4SAndroid Build Coastguard Worker return; 323*bb4ee6a4SAndroid Build Coastguard Worker } 324*bb4ee6a4SAndroid Build Coastguard Worker 325*bb4ee6a4SAndroid Build Coastguard Worker let Ok(selector) = data.try_into().map(u16::from_le_bytes) else { 326*bb4ee6a4SAndroid Build Coastguard Worker return; 327*bb4ee6a4SAndroid Build Coastguard Worker }; 328*bb4ee6a4SAndroid Build Coastguard Worker 329*bb4ee6a4SAndroid Build Coastguard Worker self.cur_offset = 0; 330*bb4ee6a4SAndroid Build Coastguard Worker 331*bb4ee6a4SAndroid Build Coastguard Worker match selector { 332*bb4ee6a4SAndroid Build Coastguard Worker FW_CFG_FILE_DIR_SELECTOR => { 333*bb4ee6a4SAndroid Build Coastguard Worker self.cur_entry = FW_CFG_FILE_DIR_SELECTOR; 334*bb4ee6a4SAndroid Build Coastguard Worker } 335*bb4ee6a4SAndroid Build Coastguard Worker FW_CFG_REVISION_SELECTOR => { 336*bb4ee6a4SAndroid Build Coastguard Worker self.cur_entry = FW_CFG_REVISION_SELECTOR; 337*bb4ee6a4SAndroid Build Coastguard Worker } 338*bb4ee6a4SAndroid Build Coastguard Worker FW_CFG_SIGNATURE_SELECTOR => { 339*bb4ee6a4SAndroid Build Coastguard Worker self.cur_entry = FW_CFG_SIGNATURE_SELECTOR; 340*bb4ee6a4SAndroid Build Coastguard Worker } 341*bb4ee6a4SAndroid Build Coastguard Worker _ => { 342*bb4ee6a4SAndroid Build Coastguard Worker let entries_index = selector as usize; 343*bb4ee6a4SAndroid Build Coastguard Worker 344*bb4ee6a4SAndroid Build Coastguard Worker // Checks if the 15th bit is set. The bit indicates whether the fw_cfg item 345*bb4ee6a4SAndroid Build Coastguard Worker // selected is archetecture specific. 346*bb4ee6a4SAndroid Build Coastguard Worker if (FW_CFG_SELECTOR_ARCH_MASK & selector) > 0 { 347*bb4ee6a4SAndroid Build Coastguard Worker self.cur_item_type = FwCfgItemType::ArchSpecificItem; 348*bb4ee6a4SAndroid Build Coastguard Worker } else { 349*bb4ee6a4SAndroid Build Coastguard Worker self.cur_item_type = FwCfgItemType::GenericItem; 350*bb4ee6a4SAndroid Build Coastguard Worker } 351*bb4ee6a4SAndroid Build Coastguard Worker 352*bb4ee6a4SAndroid Build Coastguard Worker // Check if the selector key is valid. 353*bb4ee6a4SAndroid Build Coastguard Worker if self.entries[self.cur_item_type.value()].len() <= entries_index { 354*bb4ee6a4SAndroid Build Coastguard Worker return; 355*bb4ee6a4SAndroid Build Coastguard Worker } 356*bb4ee6a4SAndroid Build Coastguard Worker 357*bb4ee6a4SAndroid Build Coastguard Worker // Checks if the 14th bit is set. The bit indicates whether the fw_cfg item 358*bb4ee6a4SAndroid Build Coastguard Worker // selected is going to be written to or only read via the data port. Since 359*bb4ee6a4SAndroid Build Coastguard Worker // writes to the data port have been deprecated as of Qemu v2.4, we don't 360*bb4ee6a4SAndroid Build Coastguard Worker // support them either. This code is only included for clarity. 361*bb4ee6a4SAndroid Build Coastguard Worker self.entries[self.cur_item_type.value()][entries_index].allow_write = 362*bb4ee6a4SAndroid Build Coastguard Worker (FW_CFG_SELECTOR_RW_MASK & selector) > 0; 363*bb4ee6a4SAndroid Build Coastguard Worker 364*bb4ee6a4SAndroid Build Coastguard Worker // Checks if the 15th bit is set. The bit indicates whether the fw_cfg item 365*bb4ee6a4SAndroid Build Coastguard Worker // selected is archetecture specific. 366*bb4ee6a4SAndroid Build Coastguard Worker if (FW_CFG_SELECTOR_ARCH_MASK & selector) > 0 { 367*bb4ee6a4SAndroid Build Coastguard Worker self.cur_item_type = FwCfgItemType::ArchSpecificItem; 368*bb4ee6a4SAndroid Build Coastguard Worker } else { 369*bb4ee6a4SAndroid Build Coastguard Worker self.cur_item_type = FwCfgItemType::GenericItem; 370*bb4ee6a4SAndroid Build Coastguard Worker } 371*bb4ee6a4SAndroid Build Coastguard Worker 372*bb4ee6a4SAndroid Build Coastguard Worker // Only the lower 14 bits are used for actual indexing. The 14th bit 373*bb4ee6a4SAndroid Build Coastguard Worker // determines whether the data item will be written to or only read 374*bb4ee6a4SAndroid Build Coastguard Worker // from the data port. The 15th bit determines whether the selected 375*bb4ee6a4SAndroid Build Coastguard Worker // configuration item is architecture specific. Therefore, we mask the 14th 376*bb4ee6a4SAndroid Build Coastguard Worker // and 15th bit off. 377*bb4ee6a4SAndroid Build Coastguard Worker self.cur_entry = selector & FW_CFG_SELECTOR_SELECT_MASK; 378*bb4ee6a4SAndroid Build Coastguard Worker } 379*bb4ee6a4SAndroid Build Coastguard Worker } 380*bb4ee6a4SAndroid Build Coastguard Worker } 381*bb4ee6a4SAndroid Build Coastguard Worker } 382*bb4ee6a4SAndroid Build Coastguard Worker } 383*bb4ee6a4SAndroid Build Coastguard Worker 384*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for FwCfgDevice { sleep(&mut self) -> anyhow::Result<()>385*bb4ee6a4SAndroid Build Coastguard Worker fn sleep(&mut self) -> anyhow::Result<()> { 386*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 387*bb4ee6a4SAndroid Build Coastguard Worker } 388*bb4ee6a4SAndroid Build Coastguard Worker wake(&mut self) -> anyhow::Result<()>389*bb4ee6a4SAndroid Build Coastguard Worker fn wake(&mut self) -> anyhow::Result<()> { 390*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 391*bb4ee6a4SAndroid Build Coastguard Worker } 392*bb4ee6a4SAndroid Build Coastguard Worker } 393*bb4ee6a4SAndroid Build Coastguard Worker 394*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)] 395*bb4ee6a4SAndroid Build Coastguard Worker mod tests { 396*bb4ee6a4SAndroid Build Coastguard Worker use serde_keyvalue::*; 397*bb4ee6a4SAndroid Build Coastguard Worker 398*bb4ee6a4SAndroid Build Coastguard Worker use super::*; 399*bb4ee6a4SAndroid Build Coastguard Worker use crate::FW_CFG_BASE_PORT; 400*bb4ee6a4SAndroid Build Coastguard Worker 401*bb4ee6a4SAndroid Build Coastguard Worker const MAGIC_BYTE: u8 = 111; 402*bb4ee6a4SAndroid Build Coastguard Worker const MAGIC_BYTE_ALT: u8 = 222; 403*bb4ee6a4SAndroid Build Coastguard Worker const FILENAME: &str = "/test/device/crosvmval"; 404*bb4ee6a4SAndroid Build Coastguard Worker const FILENAMES: [&str; 6] = [ 405*bb4ee6a4SAndroid Build Coastguard Worker "test/hello.txt", 406*bb4ee6a4SAndroid Build Coastguard Worker "user/data/mydata.txt", 407*bb4ee6a4SAndroid Build Coastguard Worker "bruschetta/user/foo", 408*bb4ee6a4SAndroid Build Coastguard Worker "valid_unix/me/home/dir/back.txt", 409*bb4ee6a4SAndroid Build Coastguard Worker "/dev/null", 410*bb4ee6a4SAndroid Build Coastguard Worker "google/unix/sys/maple.txt", 411*bb4ee6a4SAndroid Build Coastguard Worker ]; 412*bb4ee6a4SAndroid Build Coastguard Worker default_params() -> Vec<FwCfgParameters>413*bb4ee6a4SAndroid Build Coastguard Worker fn default_params() -> Vec<FwCfgParameters> { 414*bb4ee6a4SAndroid Build Coastguard Worker Vec::new() 415*bb4ee6a4SAndroid Build Coastguard Worker } 416*bb4ee6a4SAndroid Build Coastguard Worker get_contents() -> [Vec<u8>; 6]417*bb4ee6a4SAndroid Build Coastguard Worker fn get_contents() -> [Vec<u8>; 6] { 418*bb4ee6a4SAndroid Build Coastguard Worker [ 419*bb4ee6a4SAndroid Build Coastguard Worker b"CROSVM".to_vec(), 420*bb4ee6a4SAndroid Build Coastguard Worker b"GOOGLE".to_vec(), 421*bb4ee6a4SAndroid Build Coastguard Worker b"FWCONFIG".to_vec(), 422*bb4ee6a4SAndroid Build Coastguard Worker b"PIZZA".to_vec(), 423*bb4ee6a4SAndroid Build Coastguard Worker b"CHROMEOS".to_vec(), 424*bb4ee6a4SAndroid Build Coastguard Worker b"42".to_vec(), 425*bb4ee6a4SAndroid Build Coastguard Worker ] 426*bb4ee6a4SAndroid Build Coastguard Worker } 427*bb4ee6a4SAndroid Build Coastguard Worker make_device( filenames: &[&str], contents: &[Vec<u8>], params: &[FwCfgParameters], file_slots: &usize, ) -> Result<FwCfgDevice>428*bb4ee6a4SAndroid Build Coastguard Worker fn make_device( 429*bb4ee6a4SAndroid Build Coastguard Worker filenames: &[&str], 430*bb4ee6a4SAndroid Build Coastguard Worker contents: &[Vec<u8>], 431*bb4ee6a4SAndroid Build Coastguard Worker params: &[FwCfgParameters], 432*bb4ee6a4SAndroid Build Coastguard Worker file_slots: &usize, 433*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<FwCfgDevice> { 434*bb4ee6a4SAndroid Build Coastguard Worker let mut device = FwCfgDevice::new(*file_slots, params.to_owned())?; 435*bb4ee6a4SAndroid Build Coastguard Worker let count = filenames.len(); 436*bb4ee6a4SAndroid Build Coastguard Worker 437*bb4ee6a4SAndroid Build Coastguard Worker for i in 0..count { 438*bb4ee6a4SAndroid Build Coastguard Worker device.add_file( 439*bb4ee6a4SAndroid Build Coastguard Worker filenames[i], 440*bb4ee6a4SAndroid Build Coastguard Worker contents[i].clone(), 441*bb4ee6a4SAndroid Build Coastguard Worker FwCfgItemType::GenericItem, 442*bb4ee6a4SAndroid Build Coastguard Worker )?; 443*bb4ee6a4SAndroid Build Coastguard Worker } 444*bb4ee6a4SAndroid Build Coastguard Worker 445*bb4ee6a4SAndroid Build Coastguard Worker Ok(device) 446*bb4ee6a4SAndroid Build Coastguard Worker } 447*bb4ee6a4SAndroid Build Coastguard Worker from_fw_cfg_arg(options: &str) -> std::result::Result<FwCfgParameters, ParseError>448*bb4ee6a4SAndroid Build Coastguard Worker fn from_fw_cfg_arg(options: &str) -> std::result::Result<FwCfgParameters, ParseError> { 449*bb4ee6a4SAndroid Build Coastguard Worker from_key_values(options) 450*bb4ee6a4SAndroid Build Coastguard Worker } 451*bb4ee6a4SAndroid Build Coastguard Worker read_u32(device: &mut FwCfgDevice, bai: BusAccessInfo, data: &mut [u8]) -> u32452*bb4ee6a4SAndroid Build Coastguard Worker fn read_u32(device: &mut FwCfgDevice, bai: BusAccessInfo, data: &mut [u8]) -> u32 { 453*bb4ee6a4SAndroid Build Coastguard Worker let mut bytes: [u8; 4] = [0, 0, 0, 0]; 454*bb4ee6a4SAndroid Build Coastguard Worker device.read(bai, data); 455*bb4ee6a4SAndroid Build Coastguard Worker bytes[0] = data[0]; 456*bb4ee6a4SAndroid Build Coastguard Worker device.read(bai, data); 457*bb4ee6a4SAndroid Build Coastguard Worker bytes[1] = data[0]; 458*bb4ee6a4SAndroid Build Coastguard Worker device.read(bai, data); 459*bb4ee6a4SAndroid Build Coastguard Worker bytes[2] = data[0]; 460*bb4ee6a4SAndroid Build Coastguard Worker device.read(bai, data); 461*bb4ee6a4SAndroid Build Coastguard Worker bytes[3] = data[0]; 462*bb4ee6a4SAndroid Build Coastguard Worker 463*bb4ee6a4SAndroid Build Coastguard Worker u32::from_be_bytes(bytes) 464*bb4ee6a4SAndroid Build Coastguard Worker } 465*bb4ee6a4SAndroid Build Coastguard Worker read_u16(device: &mut FwCfgDevice, bai: BusAccessInfo, data: &mut [u8]) -> u16466*bb4ee6a4SAndroid Build Coastguard Worker fn read_u16(device: &mut FwCfgDevice, bai: BusAccessInfo, data: &mut [u8]) -> u16 { 467*bb4ee6a4SAndroid Build Coastguard Worker let mut bytes: [u8; 2] = [0, 0]; 468*bb4ee6a4SAndroid Build Coastguard Worker device.read(bai, data); 469*bb4ee6a4SAndroid Build Coastguard Worker bytes[0] = data[0]; 470*bb4ee6a4SAndroid Build Coastguard Worker device.read(bai, data); 471*bb4ee6a4SAndroid Build Coastguard Worker bytes[1] = data[0]; 472*bb4ee6a4SAndroid Build Coastguard Worker 473*bb4ee6a4SAndroid Build Coastguard Worker u16::from_be_bytes(bytes) 474*bb4ee6a4SAndroid Build Coastguard Worker } 475*bb4ee6a4SAndroid Build Coastguard Worker read_u8(device: &mut FwCfgDevice, bai: BusAccessInfo, data: &mut [u8]) -> u8476*bb4ee6a4SAndroid Build Coastguard Worker fn read_u8(device: &mut FwCfgDevice, bai: BusAccessInfo, data: &mut [u8]) -> u8 { 477*bb4ee6a4SAndroid Build Coastguard Worker let mut bytes: [u8; 1] = [0]; 478*bb4ee6a4SAndroid Build Coastguard Worker device.read(bai, data); 479*bb4ee6a4SAndroid Build Coastguard Worker bytes[0] = data[0]; 480*bb4ee6a4SAndroid Build Coastguard Worker u8::from_be_bytes(bytes) 481*bb4ee6a4SAndroid Build Coastguard Worker } 482*bb4ee6a4SAndroid Build Coastguard Worker read_char_56(device: &mut FwCfgDevice, bai: BusAccessInfo, data: &mut [u8]) -> String483*bb4ee6a4SAndroid Build Coastguard Worker fn read_char_56(device: &mut FwCfgDevice, bai: BusAccessInfo, data: &mut [u8]) -> String { 484*bb4ee6a4SAndroid Build Coastguard Worker let mut c: char = read_u8(device, bai, data) as char; 485*bb4ee6a4SAndroid Build Coastguard Worker let mut count = 1; //start at 1 b/c called read_u8 above 486*bb4ee6a4SAndroid Build Coastguard Worker let mut name: String = String::new(); 487*bb4ee6a4SAndroid Build Coastguard Worker while c != '\0' { 488*bb4ee6a4SAndroid Build Coastguard Worker name.push(c); 489*bb4ee6a4SAndroid Build Coastguard Worker c = read_u8(device, bai, data) as char; 490*bb4ee6a4SAndroid Build Coastguard Worker count += 1; 491*bb4ee6a4SAndroid Build Coastguard Worker } 492*bb4ee6a4SAndroid Build Coastguard Worker while count < FW_CFG_FILENAME_SIZE { 493*bb4ee6a4SAndroid Build Coastguard Worker read_u8(device, bai, data); 494*bb4ee6a4SAndroid Build Coastguard Worker count += 1; 495*bb4ee6a4SAndroid Build Coastguard Worker } 496*bb4ee6a4SAndroid Build Coastguard Worker name 497*bb4ee6a4SAndroid Build Coastguard Worker } 498*bb4ee6a4SAndroid Build Coastguard Worker get_entry( device: &mut FwCfgDevice, mut bai: BusAccessInfo, size: usize, selector: u16, ) -> Vec<u8>499*bb4ee6a4SAndroid Build Coastguard Worker fn get_entry( 500*bb4ee6a4SAndroid Build Coastguard Worker device: &mut FwCfgDevice, 501*bb4ee6a4SAndroid Build Coastguard Worker mut bai: BusAccessInfo, 502*bb4ee6a4SAndroid Build Coastguard Worker size: usize, 503*bb4ee6a4SAndroid Build Coastguard Worker selector: u16, 504*bb4ee6a4SAndroid Build Coastguard Worker ) -> Vec<u8> { 505*bb4ee6a4SAndroid Build Coastguard Worker let mut data: Vec<u8> = vec![0]; 506*bb4ee6a4SAndroid Build Coastguard Worker let mut blob: Vec<u8> = Vec::new(); 507*bb4ee6a4SAndroid Build Coastguard Worker 508*bb4ee6a4SAndroid Build Coastguard Worker bai.address = FW_CFG_BASE_PORT; 509*bb4ee6a4SAndroid Build Coastguard Worker bai.offset = FW_CFG_SELECTOR_PORT_OFFSET; 510*bb4ee6a4SAndroid Build Coastguard Worker let selector: [u8; 2] = selector.to_le_bytes(); 511*bb4ee6a4SAndroid Build Coastguard Worker device.write(bai, &selector); 512*bb4ee6a4SAndroid Build Coastguard Worker 513*bb4ee6a4SAndroid Build Coastguard Worker bai.offset = FW_CFG_DATA_PORT_OFFSET; 514*bb4ee6a4SAndroid Build Coastguard Worker 515*bb4ee6a4SAndroid Build Coastguard Worker for _i in 0..size { 516*bb4ee6a4SAndroid Build Coastguard Worker read_u8(device, bai, &mut data[..]); 517*bb4ee6a4SAndroid Build Coastguard Worker blob.push(data[0]); 518*bb4ee6a4SAndroid Build Coastguard Worker } 519*bb4ee6a4SAndroid Build Coastguard Worker 520*bb4ee6a4SAndroid Build Coastguard Worker blob 521*bb4ee6a4SAndroid Build Coastguard Worker } 522*bb4ee6a4SAndroid Build Coastguard Worker assert_read_entries(filenames: &[&str], device: &mut FwCfgDevice, bai: BusAccessInfo)523*bb4ee6a4SAndroid Build Coastguard Worker fn assert_read_entries(filenames: &[&str], device: &mut FwCfgDevice, bai: BusAccessInfo) { 524*bb4ee6a4SAndroid Build Coastguard Worker let data_len = device.entries[0][0 + FW_CFG_FILE_FIRST].data.len(); 525*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 526*bb4ee6a4SAndroid Build Coastguard Worker get_entry(device, bai, data_len, (0 + FW_CFG_FILE_FIRST) as u16), 527*bb4ee6a4SAndroid Build Coastguard Worker device.entries[0][0 + FW_CFG_FILE_FIRST].data 528*bb4ee6a4SAndroid Build Coastguard Worker ); 529*bb4ee6a4SAndroid Build Coastguard Worker 530*bb4ee6a4SAndroid Build Coastguard Worker for i in (FW_CFG_FILE_FIRST + 1)..filenames.len() { 531*bb4ee6a4SAndroid Build Coastguard Worker let data_len = device.entries[0][i].data.len(); 532*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 533*bb4ee6a4SAndroid Build Coastguard Worker get_entry(device, bai, data_len, (i + FW_CFG_FILE_FIRST) as u16), 534*bb4ee6a4SAndroid Build Coastguard Worker device.entries[0][i].data 535*bb4ee6a4SAndroid Build Coastguard Worker ); 536*bb4ee6a4SAndroid Build Coastguard Worker } 537*bb4ee6a4SAndroid Build Coastguard Worker } 538*bb4ee6a4SAndroid Build Coastguard Worker assert_read_file_dir( filenames: &[&str], contents: &[Vec<u8>], device: &mut FwCfgDevice, bai: BusAccessInfo, )539*bb4ee6a4SAndroid Build Coastguard Worker fn assert_read_file_dir( 540*bb4ee6a4SAndroid Build Coastguard Worker filenames: &[&str], 541*bb4ee6a4SAndroid Build Coastguard Worker contents: &[Vec<u8>], 542*bb4ee6a4SAndroid Build Coastguard Worker device: &mut FwCfgDevice, 543*bb4ee6a4SAndroid Build Coastguard Worker bai: BusAccessInfo, 544*bb4ee6a4SAndroid Build Coastguard Worker ) { 545*bb4ee6a4SAndroid Build Coastguard Worker let mut data: Vec<u8> = vec![0]; 546*bb4ee6a4SAndroid Build Coastguard Worker let file_count = read_u32(device, bai, &mut data[..]); 547*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(file_count, filenames.len() as u32); 548*bb4ee6a4SAndroid Build Coastguard Worker 549*bb4ee6a4SAndroid Build Coastguard Worker for i in 0..filenames.len() { 550*bb4ee6a4SAndroid Build Coastguard Worker let file_size = read_u32(device, bai, &mut data[..]); 551*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(file_size, contents[i].len() as u32); 552*bb4ee6a4SAndroid Build Coastguard Worker 553*bb4ee6a4SAndroid Build Coastguard Worker let file_select = read_u16(device, bai, &mut data[..]); 554*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(file_select - (FW_CFG_FILE_FIRST as u16), i as u16); 555*bb4ee6a4SAndroid Build Coastguard Worker 556*bb4ee6a4SAndroid Build Coastguard Worker let file_reserved = read_u16(device, bai, &mut data[..]); 557*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(file_reserved, 0); 558*bb4ee6a4SAndroid Build Coastguard Worker 559*bb4ee6a4SAndroid Build Coastguard Worker let file_name = read_char_56(device, bai, &mut data[..]); 560*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(file_name, FILENAMES[i]); 561*bb4ee6a4SAndroid Build Coastguard Worker } 562*bb4ee6a4SAndroid Build Coastguard Worker } setup_read( filenames: &[&str], contents: &[Vec<u8>], selector: u16, ) -> (FwCfgDevice, BusAccessInfo)563*bb4ee6a4SAndroid Build Coastguard Worker fn setup_read( 564*bb4ee6a4SAndroid Build Coastguard Worker filenames: &[&str], 565*bb4ee6a4SAndroid Build Coastguard Worker contents: &[Vec<u8>], 566*bb4ee6a4SAndroid Build Coastguard Worker selector: u16, 567*bb4ee6a4SAndroid Build Coastguard Worker ) -> (FwCfgDevice, BusAccessInfo) { 568*bb4ee6a4SAndroid Build Coastguard Worker let mut device = make_device( 569*bb4ee6a4SAndroid Build Coastguard Worker filenames, 570*bb4ee6a4SAndroid Build Coastguard Worker contents, 571*bb4ee6a4SAndroid Build Coastguard Worker &default_params(), 572*bb4ee6a4SAndroid Build Coastguard Worker &(filenames.len() + 5), 573*bb4ee6a4SAndroid Build Coastguard Worker ) 574*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 575*bb4ee6a4SAndroid Build Coastguard Worker let mut bai = BusAccessInfo { 576*bb4ee6a4SAndroid Build Coastguard Worker offset: FW_CFG_SELECTOR_PORT_OFFSET, 577*bb4ee6a4SAndroid Build Coastguard Worker address: FW_CFG_BASE_PORT, 578*bb4ee6a4SAndroid Build Coastguard Worker id: 0, 579*bb4ee6a4SAndroid Build Coastguard Worker }; 580*bb4ee6a4SAndroid Build Coastguard Worker let selector: [u8; 2] = selector.to_le_bytes(); 581*bb4ee6a4SAndroid Build Coastguard Worker device.write(bai, &selector); 582*bb4ee6a4SAndroid Build Coastguard Worker bai.offset = FW_CFG_DATA_PORT_OFFSET; 583*bb4ee6a4SAndroid Build Coastguard Worker 584*bb4ee6a4SAndroid Build Coastguard Worker (device, bai) 585*bb4ee6a4SAndroid Build Coastguard Worker } 586*bb4ee6a4SAndroid Build Coastguard Worker 587*bb4ee6a4SAndroid Build Coastguard Worker #[test] 588*bb4ee6a4SAndroid Build Coastguard Worker // Attempt to build FwCfgParams from key value pairs params_from_key_values()589*bb4ee6a4SAndroid Build Coastguard Worker fn params_from_key_values() { 590*bb4ee6a4SAndroid Build Coastguard Worker from_fw_cfg_arg("").expect_err("parsing empty string should fail"); 591*bb4ee6a4SAndroid Build Coastguard Worker 592*bb4ee6a4SAndroid Build Coastguard Worker let params = from_fw_cfg_arg("name=foo,path=/path/to/input").unwrap(); 593*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 594*bb4ee6a4SAndroid Build Coastguard Worker params, 595*bb4ee6a4SAndroid Build Coastguard Worker FwCfgParameters { 596*bb4ee6a4SAndroid Build Coastguard Worker name: "foo".into(), 597*bb4ee6a4SAndroid Build Coastguard Worker path: Some("/path/to/input".into()), 598*bb4ee6a4SAndroid Build Coastguard Worker string: None, 599*bb4ee6a4SAndroid Build Coastguard Worker } 600*bb4ee6a4SAndroid Build Coastguard Worker ); 601*bb4ee6a4SAndroid Build Coastguard Worker 602*bb4ee6a4SAndroid Build Coastguard Worker let params = from_fw_cfg_arg("name=bar,string=testdata").unwrap(); 603*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 604*bb4ee6a4SAndroid Build Coastguard Worker params, 605*bb4ee6a4SAndroid Build Coastguard Worker FwCfgParameters { 606*bb4ee6a4SAndroid Build Coastguard Worker name: "bar".into(), 607*bb4ee6a4SAndroid Build Coastguard Worker string: Some("testdata".into()), 608*bb4ee6a4SAndroid Build Coastguard Worker path: None, 609*bb4ee6a4SAndroid Build Coastguard Worker } 610*bb4ee6a4SAndroid Build Coastguard Worker ); 611*bb4ee6a4SAndroid Build Coastguard Worker } 612*bb4ee6a4SAndroid Build Coastguard Worker 613*bb4ee6a4SAndroid Build Coastguard Worker #[test] 614*bb4ee6a4SAndroid Build Coastguard Worker // Try to cause underflow by using a selector less than FW_CFG_FILE_FIRST but not one of the 615*bb4ee6a4SAndroid Build Coastguard Worker // special selectors attempt_underflow_read()616*bb4ee6a4SAndroid Build Coastguard Worker fn attempt_underflow_read() { 617*bb4ee6a4SAndroid Build Coastguard Worker let (_device, _bai) = setup_read( 618*bb4ee6a4SAndroid Build Coastguard Worker &FILENAMES, 619*bb4ee6a4SAndroid Build Coastguard Worker &get_contents(), 620*bb4ee6a4SAndroid Build Coastguard Worker (FW_CFG_FILE_FIRST - 0x05) as u16, 621*bb4ee6a4SAndroid Build Coastguard Worker ); 622*bb4ee6a4SAndroid Build Coastguard Worker } 623*bb4ee6a4SAndroid Build Coastguard Worker 624*bb4ee6a4SAndroid Build Coastguard Worker #[test] 625*bb4ee6a4SAndroid Build Coastguard Worker // Write a simple one byte file and confirm that an entry is properly created write_one_byte_file()626*bb4ee6a4SAndroid Build Coastguard Worker fn write_one_byte_file() { 627*bb4ee6a4SAndroid Build Coastguard Worker let mut fw_cfg = FwCfgDevice::new(100, default_params()).unwrap(); 628*bb4ee6a4SAndroid Build Coastguard Worker let data = vec![MAGIC_BYTE]; 629*bb4ee6a4SAndroid Build Coastguard Worker fw_cfg 630*bb4ee6a4SAndroid Build Coastguard Worker .add_file(FILENAME, data, FwCfgItemType::GenericItem) 631*bb4ee6a4SAndroid Build Coastguard Worker .expect("File insert failed"); 632*bb4ee6a4SAndroid Build Coastguard Worker let ind = fw_cfg.entries[0].len(); 633*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 634*bb4ee6a4SAndroid Build Coastguard Worker ind, 635*bb4ee6a4SAndroid Build Coastguard Worker FW_CFG_FILE_FIRST + 1, 636*bb4ee6a4SAndroid Build Coastguard Worker "Insertion into fw_cfg failed: Index is wrong. expected {}, got {}, 637*bb4ee6a4SAndroid Build Coastguard Worker ", 638*bb4ee6a4SAndroid Build Coastguard Worker FW_CFG_FILE_FIRST + 1, 639*bb4ee6a4SAndroid Build Coastguard Worker ind 640*bb4ee6a4SAndroid Build Coastguard Worker ); 641*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 642*bb4ee6a4SAndroid Build Coastguard Worker fw_cfg.entries[0][ind - 1].data, 643*bb4ee6a4SAndroid Build Coastguard Worker vec![MAGIC_BYTE], 644*bb4ee6a4SAndroid Build Coastguard Worker "Insertion failed: unexpected fw_cfg entry values" 645*bb4ee6a4SAndroid Build Coastguard Worker ); 646*bb4ee6a4SAndroid Build Coastguard Worker } 647*bb4ee6a4SAndroid Build Coastguard Worker 648*bb4ee6a4SAndroid Build Coastguard Worker #[test] 649*bb4ee6a4SAndroid Build Coastguard Worker // Write a simple four byte file and confirm that an entry is properly created write_four_byte_file()650*bb4ee6a4SAndroid Build Coastguard Worker fn write_four_byte_file() { 651*bb4ee6a4SAndroid Build Coastguard Worker let mut fw_cfg = FwCfgDevice::new(100, default_params()).unwrap(); 652*bb4ee6a4SAndroid Build Coastguard Worker let data = vec![MAGIC_BYTE, MAGIC_BYTE_ALT, MAGIC_BYTE, MAGIC_BYTE_ALT]; 653*bb4ee6a4SAndroid Build Coastguard Worker fw_cfg 654*bb4ee6a4SAndroid Build Coastguard Worker .add_file(FILENAME, data, FwCfgItemType::GenericItem) 655*bb4ee6a4SAndroid Build Coastguard Worker .expect("File insert failed"); 656*bb4ee6a4SAndroid Build Coastguard Worker let ind = fw_cfg.entries[0].len(); 657*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 658*bb4ee6a4SAndroid Build Coastguard Worker ind, 659*bb4ee6a4SAndroid Build Coastguard Worker FW_CFG_FILE_FIRST + 1, 660*bb4ee6a4SAndroid Build Coastguard Worker "Insertion into fw_cfg failed: Index is wrong. expected {}, got {}", 661*bb4ee6a4SAndroid Build Coastguard Worker FW_CFG_FILE_FIRST + 1, 662*bb4ee6a4SAndroid Build Coastguard Worker ind 663*bb4ee6a4SAndroid Build Coastguard Worker ); 664*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 665*bb4ee6a4SAndroid Build Coastguard Worker fw_cfg.entries[0][ind - 1].data, 666*bb4ee6a4SAndroid Build Coastguard Worker vec![MAGIC_BYTE, MAGIC_BYTE_ALT, MAGIC_BYTE, MAGIC_BYTE_ALT], 667*bb4ee6a4SAndroid Build Coastguard Worker "Insertion failed: unexpected fw_cfg entry values" 668*bb4ee6a4SAndroid Build Coastguard Worker ); 669*bb4ee6a4SAndroid Build Coastguard Worker } 670*bb4ee6a4SAndroid Build Coastguard Worker 671*bb4ee6a4SAndroid Build Coastguard Worker #[test] 672*bb4ee6a4SAndroid Build Coastguard Worker #[should_panic] 673*bb4ee6a4SAndroid Build Coastguard Worker // Attempt to add a file to an fw_cfg device w/ no fileslots and assert that nothing gets 674*bb4ee6a4SAndroid Build Coastguard Worker // inserted write_file_one_slot_expect_nop()675*bb4ee6a4SAndroid Build Coastguard Worker fn write_file_one_slot_expect_nop() { 676*bb4ee6a4SAndroid Build Coastguard Worker let mut fw_cfg = FwCfgDevice::new(0, default_params()).unwrap(); 677*bb4ee6a4SAndroid Build Coastguard Worker let data = vec![MAGIC_BYTE]; 678*bb4ee6a4SAndroid Build Coastguard Worker fw_cfg 679*bb4ee6a4SAndroid Build Coastguard Worker .add_file(FILENAME, data, FwCfgItemType::GenericItem) 680*bb4ee6a4SAndroid Build Coastguard Worker .expect("File insert failed"); 681*bb4ee6a4SAndroid Build Coastguard Worker } 682*bb4ee6a4SAndroid Build Coastguard Worker 683*bb4ee6a4SAndroid Build Coastguard Worker #[test] 684*bb4ee6a4SAndroid Build Coastguard Worker #[should_panic] 685*bb4ee6a4SAndroid Build Coastguard Worker // Attempt to add two files to an fw_cfg w/ only one fileslot and assert only first insert 686*bb4ee6a4SAndroid Build Coastguard Worker // succeeds. write_two_files_no_slots_expect_nop_on_second()687*bb4ee6a4SAndroid Build Coastguard Worker fn write_two_files_no_slots_expect_nop_on_second() { 688*bb4ee6a4SAndroid Build Coastguard Worker let mut fw_cfg = FwCfgDevice::new(1, default_params()).unwrap(); 689*bb4ee6a4SAndroid Build Coastguard Worker let data = vec![MAGIC_BYTE]; 690*bb4ee6a4SAndroid Build Coastguard Worker let data2 = vec![MAGIC_BYTE_ALT]; 691*bb4ee6a4SAndroid Build Coastguard Worker fw_cfg 692*bb4ee6a4SAndroid Build Coastguard Worker .add_file(FILENAME, data, FwCfgItemType::GenericItem) 693*bb4ee6a4SAndroid Build Coastguard Worker .expect("File insert failed"); 694*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 695*bb4ee6a4SAndroid Build Coastguard Worker fw_cfg.entries[0].len(), 696*bb4ee6a4SAndroid Build Coastguard Worker 1, 697*bb4ee6a4SAndroid Build Coastguard Worker "Insertion into fw_cfg failed: Expected {} elements, got {}", 698*bb4ee6a4SAndroid Build Coastguard Worker 1, 699*bb4ee6a4SAndroid Build Coastguard Worker fw_cfg.entries[0].len() 700*bb4ee6a4SAndroid Build Coastguard Worker ); 701*bb4ee6a4SAndroid Build Coastguard Worker fw_cfg 702*bb4ee6a4SAndroid Build Coastguard Worker .add_file(FILENAME, data2, FwCfgItemType::GenericItem) 703*bb4ee6a4SAndroid Build Coastguard Worker .expect("File insert failed"); 704*bb4ee6a4SAndroid Build Coastguard Worker } 705*bb4ee6a4SAndroid Build Coastguard Worker 706*bb4ee6a4SAndroid Build Coastguard Worker #[test] 707*bb4ee6a4SAndroid Build Coastguard Worker // Attempt to read a FwCfgDevice's signature read_fw_cfg_signature()708*bb4ee6a4SAndroid Build Coastguard Worker fn read_fw_cfg_signature() { 709*bb4ee6a4SAndroid Build Coastguard Worker let mut data: Vec<u8> = vec![0]; 710*bb4ee6a4SAndroid Build Coastguard Worker let (mut device, bai) = setup_read(&FILENAMES, &get_contents(), FW_CFG_SIGNATURE_SELECTOR); 711*bb4ee6a4SAndroid Build Coastguard Worker // To logically compare the revison vector to FW_CFG_REVISION byte-by-byte, we must use 712*bb4ee6a4SAndroid Build Coastguard Worker // to_be_bytes() since we are comparing byte arrays, not integers. 713*bb4ee6a4SAndroid Build Coastguard Worker let signature = read_u32(&mut device, bai, &mut data[..]).to_be_bytes(); 714*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(signature, FW_CFG_SIGNATURE); 715*bb4ee6a4SAndroid Build Coastguard Worker } 716*bb4ee6a4SAndroid Build Coastguard Worker 717*bb4ee6a4SAndroid Build Coastguard Worker #[test] 718*bb4ee6a4SAndroid Build Coastguard Worker // Attempt to read a FwCfgDevice's revision bit vector read_fw_cfg_revision()719*bb4ee6a4SAndroid Build Coastguard Worker fn read_fw_cfg_revision() { 720*bb4ee6a4SAndroid Build Coastguard Worker let mut data: Vec<u8> = vec![0]; 721*bb4ee6a4SAndroid Build Coastguard Worker let (mut device, bai) = setup_read(&FILENAMES, &get_contents(), FW_CFG_REVISION_SELECTOR); 722*bb4ee6a4SAndroid Build Coastguard Worker // To logically compare the revison vector to FW_CFG_REVISION byte-by-byte, we must use 723*bb4ee6a4SAndroid Build Coastguard Worker // to_be_bytes() since we are comparing byte arrays, not integers. 724*bb4ee6a4SAndroid Build Coastguard Worker let revision = read_u32(&mut device, bai, &mut data[..]).to_be_bytes(); 725*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(revision, FW_CFG_REVISION); 726*bb4ee6a4SAndroid Build Coastguard Worker } 727*bb4ee6a4SAndroid Build Coastguard Worker 728*bb4ee6a4SAndroid Build Coastguard Worker #[test] 729*bb4ee6a4SAndroid Build Coastguard Worker // Attempt to read a FwCfgDevice's file directory read_file_dir()730*bb4ee6a4SAndroid Build Coastguard Worker fn read_file_dir() { 731*bb4ee6a4SAndroid Build Coastguard Worker let contents = get_contents(); 732*bb4ee6a4SAndroid Build Coastguard Worker let (mut device, bai) = setup_read(&FILENAMES, &contents, FW_CFG_FILE_DIR_SELECTOR); 733*bb4ee6a4SAndroid Build Coastguard Worker assert_read_file_dir(&FILENAMES, &contents, &mut device, bai); 734*bb4ee6a4SAndroid Build Coastguard Worker } 735*bb4ee6a4SAndroid Build Coastguard Worker 736*bb4ee6a4SAndroid Build Coastguard Worker #[test] 737*bb4ee6a4SAndroid Build Coastguard Worker // Attempt to read all of a FwCfgDevice's entries read_fw_cfg_entries()738*bb4ee6a4SAndroid Build Coastguard Worker fn read_fw_cfg_entries() { 739*bb4ee6a4SAndroid Build Coastguard Worker let contents = get_contents(); 740*bb4ee6a4SAndroid Build Coastguard Worker let (mut device, bai) = setup_read(&FILENAMES, &contents, (0 + FW_CFG_FILE_FIRST) as u16); 741*bb4ee6a4SAndroid Build Coastguard Worker 742*bb4ee6a4SAndroid Build Coastguard Worker assert_read_entries(&FILENAMES, &mut device, bai); 743*bb4ee6a4SAndroid Build Coastguard Worker } 744*bb4ee6a4SAndroid Build Coastguard Worker 745*bb4ee6a4SAndroid Build Coastguard Worker #[test] 746*bb4ee6a4SAndroid Build Coastguard Worker // Attempt to read revision, file dir, and entries in random order to make 747*bb4ee6a4SAndroid Build Coastguard Worker // sure that proper state is maintained. read_whole_device()748*bb4ee6a4SAndroid Build Coastguard Worker fn read_whole_device() { 749*bb4ee6a4SAndroid Build Coastguard Worker let contents = get_contents(); 750*bb4ee6a4SAndroid Build Coastguard Worker let mut data: Vec<u8> = vec![0]; 751*bb4ee6a4SAndroid Build Coastguard Worker 752*bb4ee6a4SAndroid Build Coastguard Worker let (mut device, mut bai) = setup_read(&FILENAMES, &contents, FW_CFG_REVISION_SELECTOR); 753*bb4ee6a4SAndroid Build Coastguard Worker 754*bb4ee6a4SAndroid Build Coastguard Worker let revision = read_u32(&mut device, bai, &mut data[..]).to_be_bytes(); 755*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(revision, FW_CFG_REVISION); 756*bb4ee6a4SAndroid Build Coastguard Worker 757*bb4ee6a4SAndroid Build Coastguard Worker let i = FILENAMES.len() - 1; 758*bb4ee6a4SAndroid Build Coastguard Worker let data_len = device.entries[0][i].data.len(); 759*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 760*bb4ee6a4SAndroid Build Coastguard Worker get_entry(&mut device, bai, data_len, (i + FW_CFG_FILE_FIRST) as u16), 761*bb4ee6a4SAndroid Build Coastguard Worker device.entries[0][i].data 762*bb4ee6a4SAndroid Build Coastguard Worker ); 763*bb4ee6a4SAndroid Build Coastguard Worker 764*bb4ee6a4SAndroid Build Coastguard Worker bai.address = FW_CFG_BASE_PORT; 765*bb4ee6a4SAndroid Build Coastguard Worker bai.offset = FW_CFG_SELECTOR_PORT_OFFSET; 766*bb4ee6a4SAndroid Build Coastguard Worker device.write(bai, &FW_CFG_FILE_DIR_SELECTOR.to_le_bytes()); 767*bb4ee6a4SAndroid Build Coastguard Worker bai.offset = FW_CFG_DATA_PORT_OFFSET; 768*bb4ee6a4SAndroid Build Coastguard Worker 769*bb4ee6a4SAndroid Build Coastguard Worker assert_read_file_dir(&FILENAMES, &contents, &mut device, bai); 770*bb4ee6a4SAndroid Build Coastguard Worker 771*bb4ee6a4SAndroid Build Coastguard Worker let data_len = device.entries[0][FW_CFG_FILE_FIRST + 0].data.len(); 772*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 773*bb4ee6a4SAndroid Build Coastguard Worker get_entry(&mut device, bai, data_len, (0 + FW_CFG_FILE_FIRST) as u16), 774*bb4ee6a4SAndroid Build Coastguard Worker device.entries[0][FW_CFG_FILE_FIRST + 0].data 775*bb4ee6a4SAndroid Build Coastguard Worker ); 776*bb4ee6a4SAndroid Build Coastguard Worker } 777*bb4ee6a4SAndroid Build Coastguard Worker 778*bb4ee6a4SAndroid Build Coastguard Worker #[test] 779*bb4ee6a4SAndroid Build Coastguard Worker // Assert that the device maintains proper state after reads of random length. read_incorrect_bytes()780*bb4ee6a4SAndroid Build Coastguard Worker fn read_incorrect_bytes() { 781*bb4ee6a4SAndroid Build Coastguard Worker let contents = get_contents(); 782*bb4ee6a4SAndroid Build Coastguard Worker let mut data: Vec<u8> = vec![0]; 783*bb4ee6a4SAndroid Build Coastguard Worker let (mut device, mut bai) = 784*bb4ee6a4SAndroid Build Coastguard Worker setup_read(&FILENAMES, &contents, (0 + FW_CFG_FILE_FIRST) as u16); 785*bb4ee6a4SAndroid Build Coastguard Worker 786*bb4ee6a4SAndroid Build Coastguard Worker for _i in 1..1000 { 787*bb4ee6a4SAndroid Build Coastguard Worker let _random_bytes = read_u32(&mut device, bai, &mut data[..]); 788*bb4ee6a4SAndroid Build Coastguard Worker } 789*bb4ee6a4SAndroid Build Coastguard Worker 790*bb4ee6a4SAndroid Build Coastguard Worker bai.address = FW_CFG_BASE_PORT; 791*bb4ee6a4SAndroid Build Coastguard Worker device.write(bai, &FW_CFG_FILE_DIR_SELECTOR.to_le_bytes()); 792*bb4ee6a4SAndroid Build Coastguard Worker bai.offset = FW_CFG_DATA_PORT_OFFSET; 793*bb4ee6a4SAndroid Build Coastguard Worker 794*bb4ee6a4SAndroid Build Coastguard Worker for _i in 1..10000 { 795*bb4ee6a4SAndroid Build Coastguard Worker let mut data: Vec<u8> = vec![0]; 796*bb4ee6a4SAndroid Build Coastguard Worker let _random_bytes = read_u32(&mut device, bai, &mut data[..]); 797*bb4ee6a4SAndroid Build Coastguard Worker } 798*bb4ee6a4SAndroid Build Coastguard Worker 799*bb4ee6a4SAndroid Build Coastguard Worker bai.address = FW_CFG_BASE_PORT; 800*bb4ee6a4SAndroid Build Coastguard Worker bai.offset = FW_CFG_SELECTOR_PORT_OFFSET; 801*bb4ee6a4SAndroid Build Coastguard Worker device.write(bai, &FW_CFG_FILE_DIR_SELECTOR.to_le_bytes()); 802*bb4ee6a4SAndroid Build Coastguard Worker bai.offset = FW_CFG_DATA_PORT_OFFSET; 803*bb4ee6a4SAndroid Build Coastguard Worker 804*bb4ee6a4SAndroid Build Coastguard Worker assert_read_file_dir(&FILENAMES, &contents, &mut device, bai); 805*bb4ee6a4SAndroid Build Coastguard Worker 806*bb4ee6a4SAndroid Build Coastguard Worker let i = FILENAMES.len() - 1; 807*bb4ee6a4SAndroid Build Coastguard Worker 808*bb4ee6a4SAndroid Build Coastguard Worker bai.address = FW_CFG_BASE_PORT; 809*bb4ee6a4SAndroid Build Coastguard Worker bai.offset = FW_CFG_SELECTOR_PORT_OFFSET; 810*bb4ee6a4SAndroid Build Coastguard Worker device.write(bai, &(FW_CFG_FILE_FIRST + i).to_le_bytes()); 811*bb4ee6a4SAndroid Build Coastguard Worker bai.offset = FW_CFG_DATA_PORT_OFFSET; 812*bb4ee6a4SAndroid Build Coastguard Worker 813*bb4ee6a4SAndroid Build Coastguard Worker for _i in 1..1000 { 814*bb4ee6a4SAndroid Build Coastguard Worker let _random_bytes = read_u32(&mut device, bai, &mut data[..]); 815*bb4ee6a4SAndroid Build Coastguard Worker } 816*bb4ee6a4SAndroid Build Coastguard Worker 817*bb4ee6a4SAndroid Build Coastguard Worker assert_read_entries(&FILENAMES, &mut device, bai); 818*bb4ee6a4SAndroid Build Coastguard Worker } 819*bb4ee6a4SAndroid Build Coastguard Worker } 820