Skip to main content

Updater

Struct Updater 

Source
pub struct Updater<S> { /* private fields */ }
Expand description

Applies the update rules against a device’s slots.

Implementations§

Source§

impl<S: SlotStore> Updater<S>

Source

pub fn new(device: Device, store: S) -> Self

Creates an updater over a device’s slots.

§Arguments
  • device - the device’s identity and trusted author.
  • store - where its images live.
§Returns

The updater.

Source

pub fn with_delegation(self, envelope: &[u8], now: Option<u64>) -> Result<Self>

Adopts a delegation the device already held, after a restart.

A delegation is small and its envelope is self-authenticating, so the simplest place to keep one is wherever the caller already keeps device settings. Hand it back here on the way up.

§Arguments
  • envelope - the stored delegation envelope.
  • now - seconds since the Unix epoch, or None on a device with no clock.
§Returns

The updater, now accepting releases signed by the delegated key.

§Errors

Returns whatever adopt refuses.

Source

pub fn adopt(&mut self, envelope: &[u8], now: Option<u64>) -> Result<Delegation>

Takes on a delegation, moving which key may sign this device’s updates.

The caller should persist the envelope it just passed, so the device comes back up trusting the same key.

§Arguments
  • envelope - a delegation signed by the device’s trust anchor.
  • now - seconds since the Unix epoch, or None on a device with no clock.
§Returns

The delegation now in force.

§Errors

Returns Refusal::Signature if it was not signed by the trust anchor, Refusal::Rollback if its epoch does not rise above the one already held, so a retired key cannot be reinstated by replay, and Refusal::Expired or Refusal::NoClock on the same terms as a manifest.

Source

pub fn delegation(&self) -> Option<Delegation>

Returns the delegation in force, if the device holds one.

§Returns

The delegation, or None when releases are signed by the anchor itself.

Source

pub fn store(&self) -> &S

Borrows the underlying slot store.

§Returns

The store, for inspecting slot records.

Source

pub fn installed_sequence(&self) -> Result<u64>

Returns the highest sequence number any slot holds.

A new manifest must beat this, not merely the running image, so an older release cannot be slipped in alongside a newer one that is already staged. Failed slots count too: re-releasing a sequence that already failed would let a captured image be replayed.

§Returns

The highest sequence number present, or 0 if every slot is empty.

§Errors

Returns a refusal if a slot record cannot be read.

Source

pub fn begin(&mut self, envelope: &[u8]) -> Result<Staging<'_, S>>

Checks a manifest and opens the slot it names for writing.

§Arguments
  • envelope - the signed manifest offered to this device.
§Returns

A Staging ready to take the image, once every check that can be made without the image has passed.

§Errors

Returns whatever begin_at refuses. A manifest that carries an expiry is refused, because a device with no clock cannot honour one; call begin_at with the time if it has one.

Source

pub fn begin_at( &mut self, envelope: &[u8], now: Option<u64>, ) -> Result<Staging<'_, S>>

Checks a manifest against the current time and opens the slot it names.

§Arguments
  • envelope - the signed manifest offered to this device.
  • now - seconds since the Unix epoch, or None on a device with no clock.
§Returns

A Staging ready to take the image, once every check that can be made without the image has passed.

§Errors

Returns Refusal::Signature if the envelope is not from the trusted author, Refusal::WrongDevice if it is for a different vendor or class, Refusal::Expired if its expiry has passed, Refusal::NoClock if it expires and now is None, Refusal::Rollback if it would not move the device forward, Refusal::SlotTooSmall if the image cannot fit, or Refusal::WrongState if it names the slot the device would fall back to.

Source

pub fn resume_at( &mut self, envelope: &[u8], now: Option<u64>, ) -> Result<Staging<'_, S>>

Opens a slot for an image, continuing a transfer that was cut off.

A slow radio can spend half an hour on a single image, so a link that drops near the end must not mean starting again. If the slot already holds part of exactly this image, the transfer picks up where it stopped; anything else starts over, because mixing two images produces neither. An image whose last byte arrived but which was never settled counts as picking up where it stopped, so a reset in that gap costs nothing.

§Arguments
  • envelope - the signed manifest offered to this device.
  • now - seconds since the Unix epoch, or None on a device with no clock.
§Returns

A Staging positioned after whatever already arrived, which progress reports.

§Errors

Returns whatever begin_at refuses.

Source

pub fn stage(&mut self, envelope: &[u8], image: &[u8]) -> Result<u8>

Checks a manifest and stages an image already held whole.

§Arguments
  • envelope - the signed manifest.
  • image - the whole image.
§Returns

The slot the image was staged into.

§Errors

Returns whatever begin or Staging::finish refuses.

Source

pub fn stage_at( &mut self, envelope: &[u8], image: &[u8], now: Option<u64>, ) -> Result<u8>

Checks a manifest against the current time and stages an image held whole.

§Arguments
  • envelope - the signed manifest.
  • image - the whole image.
  • now - seconds since the Unix epoch, or None on a device with no clock.
§Returns

The slot the image was staged into.

§Errors

Returns whatever begin_at or Staging::finish refuses.

Source

pub fn on_boot(&mut self) -> Result<Boot>

Decides what to run, and records that decision before returning it.

Call this once per boot, before jumping to an image. A staged image becomes pending here, so if the device resets before confirming, the next call sees a pending slot and reverts.

§Returns

What the bootloader should run.

§Errors

Returns Refusal::NothingToRevert if there is no image to fall back to.

Source

pub fn confirm(&mut self) -> Result<u8>

Reports the running image healthy, making it the one to fall back to.

The slot the device previously fell back to is erased, which is what frees it to receive the next update.

§Returns

The slot that is now confirmed.

§Errors

Returns Refusal::WrongState if no image is pending, so a confirmation that arrives twice, or from an image nobody is trying, does nothing.

Source

pub fn revert(&mut self) -> Result<u8>

Gives up on the pending image and goes back to the confirmed one.

§Returns

The slot the device falls back to.

§Errors

Returns Refusal::WrongState if no image is pending, or Refusal::NothingToRevert if there is nothing to fall back to.

Source

pub fn provision(&mut self, slot: u8, sequence: u64) -> Result<()>

Marks a slot confirmed at first provisioning, when nothing was staged.

A device leaves the factory already running an image that no update installed. Without this there is no fallback for the first update to return to.

§Arguments
  • slot - the slot the factory image occupies.
  • sequence - the sequence number of that image.
§Returns

Ok(()) once the slot is confirmed.

§Errors

Returns Refusal::WrongState if any slot is already confirmed.

Auto Trait Implementations§

§

impl<S> Freeze for Updater<S>
where S: Freeze,

§

impl<S> RefUnwindSafe for Updater<S>
where S: RefUnwindSafe,

§

impl<S> Send for Updater<S>
where S: Send,

§

impl<S> Sync for Updater<S>
where S: Sync,

§

impl<S> Unpin for Updater<S>
where S: Unpin,

§

impl<S> UnsafeUnpin for Updater<S>
where S: UnsafeUnpin,

§

impl<S> UnwindSafe for Updater<S>
where S: 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> Same for T

Source§

type Output = T

Should always be Self
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.