@@ -498,48 +498,53 @@ impl idl::InOrderUpdateImpl for ServerImpl<'_> {
498498 UpdateState :: Finished | UpdateState :: NoUpdate => ( ) ,
499499 }
500500
501- let image = match ( component, slot) {
501+ self . image = match ( component, slot) {
502502 ( RotComponent :: Hubris , SlotId :: A )
503503 | ( RotComponent :: Hubris , SlotId :: B ) => {
504- let active = match bootstate ( )
505- . map_err ( |_| UpdateError :: MissingHandoffData ) ?
506- . active
507- {
508- stage0_handoff:: RotSlot :: A => SlotId :: A ,
509- stage0_handoff:: RotSlot :: B => SlotId :: B ,
510- } ;
511- if active == slot {
504+ // Fail early on attempt to update the running image.
505+ if same_image ( component, slot) {
512506 return Err ( UpdateError :: InvalidSlotIdForOperation . into ( ) ) ;
513507 }
508+
514509 // Rollback protection will be implemented by refusing to set
515- // boot preference to an image that has a lower EPOC vale in the
516- // caboose.
517- //
510+ // boot preference to an image that has a lower EPOC value in
511+ // its caboose.
518512 // Setting the boot preference before updating would sidestep that
519513 // protection. So, we will fail the prepare step if any
520514 // preference settings are selecting the update target image.
515+ //
516+ // After the update, the boot image selection will be based on:
517+ // - there being only one properly signed image, or
518+ // - transient boot selection (highest priority), or
519+ // - pending persistent selection (altering the persistent
520+ // selection)
521+ // - persistent preference if neither of the above was used.
522+
521523 let ( persistent, pending_persistent, transient) =
522524 self . boot_preferences ( ) ?;
525+
526+ // The transient preference must not select the update target.
523527 if let Some ( pref) = transient {
524- if active ! = pref {
528+ if slot = = pref {
525529 return Err ( UpdateError :: InvalidPreferredSlotId . into ( ) ) ;
526530 }
527531 }
532+ // If there is a pending persistent preference, it must
533+ // not select the update target.
528534 if let Some ( pref) = pending_persistent {
529- if active ! = pref {
535+ if slot = = pref {
530536 return Err ( UpdateError :: InvalidPreferredSlotId . into ( ) ) ;
531537 }
532- }
533- if active != persistent {
538+ } else if slot == persistent {
539+ // If there is no pending persistent preference, then the
540+ // persistent preference must select the currently active image.
534541 return Err ( UpdateError :: InvalidPreferredSlotId . into ( ) ) ;
535542 }
536543 Some ( ( component, slot) )
537544 }
538545 ( RotComponent :: Stage0 , SlotId :: B ) => Some ( ( component, slot) ) ,
539546 _ => return Err ( UpdateError :: InvalidSlotIdForOperation . into ( ) ) ,
540547 } ;
541-
542- self . image = image;
543548 self . state = UpdateState :: InProgress ;
544549 ringbuf_entry ! ( Trace :: State ( self . state) ) ;
545550 self . next_block = None ;
0 commit comments