@@ -498,22 +498,46 @@ impl idl::InOrderUpdateImpl for ServerImpl<'_> {
498498 UpdateState :: Finished | UpdateState :: NoUpdate => ( ) ,
499499 }
500500
501- self . image = match ( component, slot) {
501+ let image = match ( component, slot) {
502502 ( RotComponent :: Hubris , SlotId :: A )
503- | ( RotComponent :: Hubris , SlotId :: B )
504- | ( RotComponent :: Stage0 , SlotId :: B ) => Some ( ( component, slot) ) ,
503+ | ( RotComponent :: Hubris , SlotId :: B ) => {
504+ let active = match bootstate ( ) . map_err ( |_| UpdateError :: MissingHandoffData ) ?. active {
505+ stage0_handoff:: RotSlot :: A => SlotId :: A ,
506+ stage0_handoff:: RotSlot :: B => SlotId :: B ,
507+ } ;
508+ if active == slot {
509+ return Err ( UpdateError :: InvalidSlotIdForOperation . into ( ) ) ;
510+ }
511+ // Since we will be enforcing rollback protection at the time when the
512+ // boot preference is set, we cannot yet have the alternate image as the
513+ // preferred image. The full image needs to be in place in order to
514+ // evaluate the policy.
515+ let ( persistent, pending_persistent, transient) = self . boot_preferences ( ) ?;
516+ if let Some ( pref) = transient {
517+ if active != pref {
518+ return Err ( UpdateError :: InvalidPreferredSlotId . into ( ) ) ;
519+ }
520+ }
521+ if let Some ( pref) = pending_persistent {
522+ if active != pref {
523+ return Err ( UpdateError :: InvalidPreferredSlotId . into ( ) )
524+ }
525+ }
526+ if active != persistent {
527+ return Err ( UpdateError :: InvalidPreferredSlotId . into ( ) )
528+ }
529+ Some ( ( component, slot) )
530+ }
531+ ( RotComponent :: Stage0 , SlotId :: B ) => Some ( ( component, slot) ) ,
505532 _ => return Err ( UpdateError :: InvalidSlotIdForOperation . into ( ) ) ,
506533 } ;
534+
535+
536+ self . image = image;
507537 self . state = UpdateState :: InProgress ;
508538 ringbuf_entry ! ( Trace :: State ( self . state) ) ;
509539 self . next_block = None ;
510540 self . fw_cache . fill ( 0 ) ;
511- // The sequence: [update, set transient preference, update] is legal.
512- // Clear any stale transient preference before update.
513- // Stage0 doesn't support transient override.
514- if component == RotComponent :: Hubris {
515- set_hubris_transient_override ( None ) ;
516- }
517541 Ok ( ( ) )
518542 }
519543
0 commit comments