Skip to main content

ZbiContainer

Struct ZbiContainer 

Source
pub struct ZbiContainer<B: SplitByteSlice> {
    pub header: Ref<B, ZbiHeader>,
    /* private fields */
}
Expand description

Main structure to work with ZBI format.

It allows to create valid buffer as well as parse existing one. Both cases would allow to iterate over elements in the container via ZbiContainer::iter or ZbiContainer::iter_mut.

Fields§

§header: Ref<B, ZbiHeader>

Container specific ZbiHeader, witch would be first element if ZBI buffer.

header.length would show how many bytes after this header is used for ZBI elements and padding.

header.type_ is always ZbiType::Container

Implementations§

Source§

impl<B: SplitByteSlice> ZbiContainer<B>

Source

pub fn get_payload_length_u32(&self) -> u32

Returns current container length as u32. Length doesn’t include container header, only items and padding.

Source

pub fn get_payload_length_usize(&self) -> usize

Returns current container length as usize. Length doesn’t include container header, only items and padding.

Source

pub fn container_size(&self) -> Result<usize, ZbiError>

Returns the total size including the ZBI container header, payload length after padding.

Source

pub fn iter( &self, ) -> ZbiContainerIterator<impl SplitByteSlice + IntoByteSlice<'_> + Default + Debug + PartialEq + '_>

Immutable iterator over ZBI elements. First element is first ZBI element after container header. Container header is not available via iterator.

Source

pub fn get_bootable_kernel_item( &self, ) -> Result<ZbiItem<impl SplitByteSlice + Default + Debug + PartialEq + '_>, ZbiError>

Validates if ZBI is bootable for the target platform. And returns ZBI item kernel on success.

§Returns
Source

pub fn get_kernel_entry_and_reserved_memory_size( &self, ) -> Result<(u64, u64), ZbiError>

Returns the ZBI kernel entry and reserved_memory_size field value if the container is a bootable ZBI kernel.

§Returns
  • Returns Ok((entry, reserved_memory_size)) on success.
  • Returns Err if container is not a bootable ZBI kernel or is truncated.
Source

pub fn get_buffer_size_for_kernel_relocation(&self) -> Result<usize, ZbiError>

Computes the required buffer size needed for relocating this ZBI kernel.

§Returns
  • Returns Ok(size) on success.
  • Returns Err if container is not a valid bootable ZBI kernel.
Source

pub fn parse(buffer: B) -> Result<Self, ZbiError>

Creates ZbiContainer from provided buffer.

Buffer must be aligned to ZBI_ALIGNMENT_USIZE (align_buffer could be used for that). If buffer is mutable than container can be mutable.

§Returns
  • Ok(ZbiContainer) - if buffer is aligned and contain valid buffer.
  • Err(ZbiError) - if error occurred.
Source§

impl<B: SplitByteSliceMut + PartialEq> ZbiContainer<B>

Source

pub fn new(buffer: B) -> Result<Self, ZbiError>

Creates new empty ZbiContainer using provided buffer.

§Returns
  • Ok(ZbiContainer) - on success
  • Err(ZbiError) - on error
Source

pub fn get_next_payload(&mut self) -> Result<&mut [u8], ZbiError>

Get payload slice for the next ZBI entry Next.

Next entry should be added using ZbiContainer::create_entry.

This is useful when it’s non-trivial to determine the length of a payload ahead of time - for example, loading a variable-length string from persistent storage.

Rather than loading the payload into a temporary buffer, determining the length, then copying it into the ZBI, this function allows loading data directly into the ZBI. Since this buffer is currently unused area, loading data here does not affect the ZBI until zbi_create_entry() is called.

§Example
let next_payload = container.get_next_payload().unwrap();
next_payload[..payload_to_use.len()].copy_from_slice(&payload_to_use[..]);

container
    .create_entry(ZbiType::KernelX64, 0, ZbiFlags::default(), payload_to_use.len())
    .unwrap();

assert_eq!(container.iter().count(), 1);
assert_eq!(&*container.iter().next().unwrap().payload, &payload_to_use[..]);
§Returns:

Ok(&mut [u8]) - on success; slice of buffer where next entries payload would be located. Err(ZbiError::TooBig) - if buffer is not big enough for new element without payload.

Source

pub fn create_entry_with_payload( &mut self, type_: ZbiType, extra: u32, flags: ZbiFlags, payload: &[u8], ) -> Result<(), ZbiError>

Creates a new ZBI entry with the provided payload.

The new entry is aligned to ZBI_ALIGNMENT_USIZE. The capacity of the base ZBI must be large enough to fit the new entry.

The ZbiFlags::VERSION is unconditionally set for the new entry.

The ZbiFlags::CRC32 flag yields an error because CRC computation is not yet supported.

§Arguments
  • type_ - The new entry’s type
  • extra - The new entry’s type-specific data
  • flags - The new entry’s flags
  • payload - The payload, copied into the new entry
§Returns:
§Example
container
    .create_entry_with_payload(ZbiType::KernelX64, 0, ZbiFlags::default(), &[1, 2, 3, 4])
    .unwrap();
assert_eq!(container.iter().count(), 1);
assert_eq!(&*container.iter().next().unwrap().payload, &[1, 2, 3, 4]);
Source

pub fn create_entry( &mut self, type_: ZbiType, extra: u32, flags: ZbiFlags, payload_length: usize, ) -> Result<(), ZbiError>

Creates a new ZBI entry and returns a pointer to the payload.

The new entry is aligned to ZBI_ALIGNMENT_USIZE. The capacity of the base ZBI must be large enough to fit the new entry.

The ZbiFlags::VERSION is unconditionally set for the new entry.

The ZbiFlags::CRC32 flag yields an error because CRC computation is not yet supported.

§Arguments
  • type_ - The new entry’s type.
  • extra - The new entry’s type-specific data.
  • flags - The new entry’s flags.
  • payload_length - The length of the new entry’s payload.
§Returns
§Example
let next_payload = container.get_next_payload().unwrap();
next_payload[..payload_to_use.len()].copy_from_slice(&payload_to_use[..]);

container
    .create_entry(ZbiType::KernelX64, 0, ZbiFlags::default(), payload_to_use.len())
    .unwrap();

assert_eq!(container.iter().count(), 1);
assert_eq!(&*container.iter().next().unwrap().payload, &payload_to_use[..]);
Source

pub fn extend( &mut self, other: &ZbiContainer<impl SplitByteSlice + PartialEq>, ) -> Result<(), ZbiError>

Extends a ZBI container with another container’s payload.

§Arguments
  • other - The container to copy the payload from.
§Returns
§Example
let mut container_0 = ZbiContainer::new(&mut buffer[..]).unwrap();
container_0
    .create_entry_with_payload(ZbiType::DebugData, 0, ZbiFlags::default(), &[0, 1])
    .unwrap();

let mut container_1 = ZbiContainer::new(&mut buffer[..]).unwrap();
container_1
    .create_entry_with_payload(ZbiType::KernelX64, 0, ZbiFlags::default(), &[0, 1, 3, 4])
    .unwrap();

container_0.extend(&container_1).unwrap();

assert_eq!(container_0.iter().count(), 2);
Source

pub fn extend_items<'a>( &mut self, iter: ZbiContainerIterator<impl SplitByteSlice + Default + Debug + PartialEq + 'a>, ) -> Result<(), ZbiError>

Extends a ZBI container with another ZBI item.

§Arguments
  • iter - ZBI container iterator. Elements starting from iter till the end are to be appended to the container.
§Returns
Source

pub fn extend_unaligned(&mut self, other: &[u8]) -> Result<(), ZbiError>

Extends with another ZBI container stored on a potentially unaligned buffer.

The method copies other into the unused space first before checking validity and extending. Thus if other.len() is greater than the remaining space in the container, it it will be rejected, regardless of the actual container size.

Source§

impl<B: SplitByteSlice + PartialEq + DerefMut> ZbiContainer<B>

Source

pub fn iter_mut( &mut self, ) -> ZbiContainerIterator<impl SplitByteSliceMut + Debug + Default + PartialEq + '_>

Mutable iterator over ZBI elements. First element is first ZBI element after container header. Container header is not available via iterator.

Trait Implementations§

Source§

impl<B: Debug + SplitByteSlice> Debug for ZbiContainer<B>

Source§

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

Formats the value using the given formatter. Read more
Source§

impl<B: PartialEq + SplitByteSlice> PartialEq for ZbiContainer<B>

Source§

fn eq(&self, other: &ZbiContainer<B>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<B: PartialEq + SplitByteSlice> StructuralPartialEq for ZbiContainer<B>

Auto Trait Implementations§

§

impl<B> Freeze for ZbiContainer<B>
where B: Freeze,

§

impl<B> RefUnwindSafe for ZbiContainer<B>
where B: RefUnwindSafe,

§

impl<B> Send for ZbiContainer<B>
where B: Send,

§

impl<B> Sync for ZbiContainer<B>
where B: Sync,

§

impl<B> Unpin for ZbiContainer<B>
where B: Unpin,

§

impl<B> UnsafeUnpin for ZbiContainer<B>
where B: UnsafeUnpin,

§

impl<B> UnwindSafe for ZbiContainer<B>
where B: 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 = Infallible

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.