Skip to main content

Image

Struct Image 

pub struct Image<R> {
    source: R,
    block_size: u32,
    blocks: u32,
    offsets: HeaderOffsets,
}
Expand description

UBI image whose volumes are read through the headers of its blocks.

It reads only the EC and VID headers to find the blocks of a volume, and reads data only when asked. Unlike super::ImageReader, it doesn’t need a block buffer.

Any invalid header in the image is an error, also in blocks of other volumes. When the kernel attaches a device, it skips some damaged blocks instead.

use std::fs::File;

use flashkit_ubi::flashkit_io::ReadAt as _;
use flashkit_ubi::{HeaderOffsets, Image, VolumeTable};

let offsets = HeaderOffsets::from_io_sizes(4096, 4096).ok_or("invalid I/O size")?;
let image = Image::new(File::open("system.ubi")?, 256 * 1024, offsets)?;
let mut buffer = vec![0; VolumeTable::BUFFER_LEN];
let table = image.volume_table(&mut buffer)?;
let (id, record) = table.find(b"rootfs").ok_or("no rootfs volume")?;
let map = vec![0; usize::try_from(record.reserved_blocks)?];
let rootfs = image.volume(id, &record, map)?;

let mut magic = [0; 4];
rootfs.read_exact_at(0, &mut magic)?;

Fields§

§source: R§block_size: u32§blocks: u32§offsets: HeaderOffsets

Implementations§

§

impl<R: ReadAt> Image<R>

pub fn new( source: R, block_size: u32, offsets: HeaderOffsets, ) -> Result<Self, ImageError<R::Error>>

Opens the image in source.

block_size must be the erase block size of the flash the image was built for, and every block with an EC header must have offsets. See super::ImageReader::new.

§Errors

Returns ImageError::Offsets if the kernel rejects offsets for this block size, ImageError::Size if the size of the image can’t be read, ImageError::PartialBlock if the image ends in the middle of a block and ImageError::TooManyBlocks if the image has more blocks than fit into a u32.

pub const fn blocks(&self) -> u32

Returns the number of blocks in the image.

pub const fn leb_size(&self) -> u32

Returns the size of a logical eraseblock.

pub fn into_inner(self) -> R

Returns the source of the image.

pub fn volume_table<'b>( &self, buffer: &'b mut [u8], ) -> Result<VolumeTable<'b>, ImageError<R::Error>>

Reads the volume table into buffer.

buffer must fit the table. VolumeTable::BUFFER_LEN bytes are always enough. Like the kernel, it uses the copy in LEB 0 of the layout volume, or the copy in LEB 1 if LEB 0 is invalid. An image without any data has an empty table.

§Errors

Returns ImageError::BufferLength if buffer is too short, ImageError::NoVolumeTable if the image contains data but no layout volume, ImageError::VolumeTable if neither copy is valid, and another error if a block can’t be read or has an invalid header.

pub fn volume<M: AsRef<[u32]> + AsMut<[u32]>>( &self, id: u32, record: &VolumeRecord<'_>, map: M, ) -> Result<VolumeReader<'_, R, M>, ImageError<R::Error>>

Finds the blocks of volume id and returns a reader over its data.

record is the record of the volume in the volume table. map stores the block of each logical eraseblock. It must have exactly record.reserved_blocks entries, and their values are overwritten. Pass a slice, an array or a Vec.

If two blocks contain the same logical eraseblock, it uses the one with the higher sequence number, like the kernel. If that block is a copy that wear leveling made and its data doesn’t match its CRC, it uses the other one.

§Errors

Returns ImageError::UpdateMarker if the volume has an unfinished update, ImageError::BufferLength if map has the wrong length, ImageError::Header if a block has an invalid header or doesn’t match record, ImageError::DuplicateBlock if two blocks contain the same logical eraseblock with the same sequence number, ImageError::MissingBlock if a static volume misses a logical eraseblock, and ImageError::Read if a block can’t be read.

fn scan( &self, id: u32, map: &mut [u32], each: impl FnMut(u32, &VidHeader) -> Result<(), ImageError<R::Error>>, ) -> Result<bool, ImageError<R::Error>>

Fills map with the blocks of volume id and calls each for each block of the volume. Returns whether any block contains data.

fn vid_header( &self, block: u32, headers: &mut ImageHeaders, ) -> Result<Option<VidHeader>, ImageError<R::Error>>

Reads the headers of block and returns its VID header, if it contains data.

fn newer( &self, first: u32, second: u32, vid: &VidHeader, ) -> Result<u32, ImageError<R::Error>>

Returns which of two blocks with the same logical eraseblock the kernel uses, like its ubi_compare_lebs.

fn data_crc_matches( &self, block: u32, vid: &VidHeader, ) -> Result<bool, ImageError<R::Error>>

Returns whether the data of a copied block matches its CRC.

fn read( &self, block: u32, offset: u32, buf: &mut [u8], ) -> Result<(), ImageError<R::Error>>

Reads buf.len() bytes from block, starting offset bytes into it.

Trait Implementations§

§

impl<R> Debug for Image<R>

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<R> Freeze for Image<R>
where R: Freeze,

§

impl<R> RefUnwindSafe for Image<R>
where R: RefUnwindSafe,

§

impl<R> Send for Image<R>
where R: Send,

§

impl<R> Sync for Image<R>
where R: Sync,

§

impl<R> Unpin for Image<R>
where R: Unpin,

§

impl<R> UnsafeUnpin for Image<R>
where R: UnsafeUnpin,

§

impl<R> UnwindSafe for Image<R>
where R: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.