| 1150 | } |
| 1151 | |
| 1152 | pub fn read_ec_flash(&self, offset: u32, size: u32) -> EcResult<Vec<u8>> { |
| 1153 | let mut flash_bin: Vec<u8> = Vec::with_capacity(EC_FLASH_SIZE); |
| 1154 | |
| 1155 | // Read in chunks of size 0x80 or just a single small chunk |
| 1156 | let (chunk_size, chunks) = if size <= 0x80 { |
| 1157 | (size, 1) |
| 1158 | } else { |
| 1159 | (0x80, size / 0x80) |
| 1160 | }; |
| 1161 | for chunk_no in 0..chunks { |
| 1162 | #[cfg(feature = "uefi")] |
| 1163 | if shell_get_execution_break_flag() { |
| 1164 | // TODO: We don't want to crash here. But returning no data doesn't seem optimal |
| 1165 | // either |
| 1166 | // return Err(EcError::DeviceError("Execution interrupted".to_string())); |
| 1167 | println!("Execution interrupted"); |
| 1168 | return Ok(vec![]); |
| 1169 | } |
| 1170 | |
| 1171 | let offset = offset + chunk_no * chunk_size; |
| 1172 | let cur_chunk_size = std::cmp::min(chunk_size, size - chunk_no * chunk_size); |
| 1173 | if log_enabled!(Level::Warn) { |
| 1174 | if chunk_no % 10 == 0 { |
| 1175 | println!(); |
| 1176 | print!( |
| 1177 | "Reading chunk {:>4}/{:>4} ({:>6}/{:>6}): X", |
| 1178 | chunk_no, |
| 1179 | chunks, |
| 1180 | offset, |
| 1181 | cur_chunk_size * chunks |
| 1182 | ); |
| 1183 | } else { |
| 1184 | print!("X"); |
| 1185 | } |
| 1186 | } |
| 1187 | |
| 1188 | let chunk = self.read_ec_flash_chunk(offset, cur_chunk_size); |
| 1189 | match chunk { |
| 1190 | Ok(chunk) => { |
| 1191 | flash_bin.extend(chunk); |
| 1192 | } |
| 1193 | Err(err) => { |
| 1194 | error!(" Failed to read chunk: {:?}", err); |
| 1195 | } |
| 1196 | } |
| 1197 | os_specific::sleep(100); |
| 1198 | } |
| 1199 | |
| 1200 | Ok(flash_bin) |
| 1201 | } |
| 1202 | |
| 1203 | pub fn get_entire_ec_flash(&self) -> EcResult<Vec<u8>> { |
| 1204 | self.flash_notify(MecFlashNotify::AccessSpi)?; |