grisp_updater_system behaviour (grisp_updater v2.3.0)

View Source

Summary

Callbacks

Roll back any preparation done during an in-progress update (on cancel).

Return the global #target{} representing the whole updatable medium (e.g., disk/flash device and its base offset).

Report current {Boot, Valid, Next} systems

Optionally force which system slot to update and provide its base write target as #target{}. If you implement this and return {ok, SysId, SystemTarget}, the manager will skip manifest-structure-based target selection and use the provided slot/target. If you do NOT implement this callback, the manager selects the target based on the manifest's MBR/GPT structure and the current/valid slots. Returning {error, _} aborts the update (no fallback).

Initialize the platform-specific HAL and return an opaque State. This State is passed to all subsequent callbacks. Keep probing lightweight (e.g., read environment, detect active slot), avoid writes here.

Notified after a single object finished writing. Perform post-write actions such as sync, metadata updates, or per-object validation.

Translate an object's target specification into a concrete #target{} within the selected system target (SysTarget). For example

Prepare the chosen system slot for update (e.g., unmount filesystem, ensure not the booted slot). Must not write object data. Return the updated State or an error to abort.

Record that the target system slot was updated successfully (e.g., set next-boot slot, write bootloader state) after all objects completed. Persist changes as needed and return updated State.

Termination hook for cleanup. Reason indicates shutdown or error cause.

Guaranteed end-of-update cleanup. Called exactly once after the update attempt concludes when system_update_init/2 previously succeeded, regardless of outcome (success, failure, or cancel during updating). Return the updated State. Cleanup must be best-effort and not fail.

Called once the update manifest is loaded and before any object is written. Provides high-level firmware metadata (product, version, objects, etc.) so the HAL can persist or validate it and keep any data it needs in its State.

Called once the entire update succeeded (all objects).

Validate the currently running system (e.g., clear update-pending flag, commit the active slot). Typically called on first boot after the update has been applied and verified.

Types

block_encoding()

-type block_encoding() ::
          #raw_encoding{block_path :: binary()} |
          #gzip_encoding{block_size :: non_neg_integer(),
                         block_crc :: integer(),
                         block_hash_type :: atom(),
                         block_hash_data :: binary(),
                         block_path :: binary()}.

system_id()

-type system_id() :: non_neg_integer().

target()

-type target() ::
          #target{device :: binary(),
                  offset :: non_neg_integer(),
                  size :: undefined | non_neg_integer(),
                  total :: undefined | non_neg_integer()}.

target_context()

-type target_context() :: global | system.

target_spec()

-type target_spec() ::
          #raw_target_spec{context :: target_context(), offset :: integer()} |
          #file_target_spec{context :: target_context(), path :: binary()}.

Callbacks

system_cancel_update(State)

-callback system_cancel_update(State :: term()) -> {ok, State :: term()}.

Roll back any preparation done during an in-progress update (on cancel).

system_get_global_target(State)

(optional)
-callback system_get_global_target(State :: term()) -> GlobalTarget :: target().

Return the global #target{} representing the whole updatable medium (e.g., disk/flash device and its base offset).

Optional: implement when your manifests use raw targets with context=global or when the manager must derive absolute addresses from structure. If not implemented and required, the manager fails with a clear error (missing_global_target).

system_get_systems(State)

-callback system_get_systems(State :: term()) ->
                                {BootSysId :: system_id() | removable,
                                 ValidatedSysId :: system_id(),
                                 NextSysId :: system_id()}.

Report current {Boot, Valid, Next} systems:

  • Boot: slot from which the software is currently running, or 'removable' when running off removable media
  • Valid: last validated slot (safe to update from)
  • Next: slot that will boot on the next restart

system_get_updatable(State)

(optional)
-callback system_get_updatable(State :: term()) ->
                                  {ok, SysId :: system_id(), SystemTarget :: target()} |
                                  {error, Reason :: term}.

Optionally force which system slot to update and provide its base write target as #target{}. If you implement this and return {ok, SysId, SystemTarget}, the manager will skip manifest-structure-based target selection and use the provided slot/target. If you do NOT implement this callback, the manager selects the target based on the manifest's MBR/GPT structure and the current/valid slots. Returning {error, _} aborts the update (no fallback).

system_init(Opts)

-callback system_init(Opts :: map()) -> {ok, State :: term()} | {error, term()}.

Initialize the platform-specific HAL and return an opaque State. This State is passed to all subsequent callbacks. Keep probing lightweight (e.g., read environment, detect active slot), avoid writes here.

system_object_updated(State, Object, Target)

(optional)
-callback system_object_updated(State :: term(),
                                Object ::
                                    #object{type :: atom(),
                                            product :: undefined | binary(),
                                            version :: undefined | binary(),
                                            desc :: undefined | binary(),
                                            target :: target_spec(),
                                            blocks ::
                                                [#block{id :: non_neg_integer(),
                                                        data_offset :: integer(),
                                                        data_size :: non_neg_integer(),
                                                        data_crc :: integer(),
                                                        data_hash_type :: atom(),
                                                        data_hash_data :: binary(),
                                                        encoding :: block_encoding()}],
                                            block_count :: non_neg_integer(),
                                            data_size :: non_neg_integer(),
                                            block_size :: non_neg_integer()},
                                Target ::
                                    #target{device :: binary(),
                                            offset :: non_neg_integer(),
                                            size :: undefined | non_neg_integer(),
                                            total :: undefined | non_neg_integer()}) ->
                                   {ok, State :: term()} | {error, term()}.

Notified after a single object finished writing. Perform post-write actions such as sync, metadata updates, or per-object validation.

system_prepare_target(State, SysId, SysTarget, Spec)

(optional)
-callback system_prepare_target(State :: term(),
                                SysId :: system_id(),
                                SysTarget :: target(),
                                Spec :: target_spec()) ->
                                   {ok, Target :: target()}.

Translate an object's target specification into a concrete #target{} within the selected system target (SysTarget). For example:

  • file_target_spec(context=system): derive the per-slot file path
  • raw_target_spec(context=system): add object offset to system base If not implemented, the manager provides sensible defaults.

system_prepare_update(State, SysId)

-callback system_prepare_update(State :: term(), SysId :: system_id()) ->
                                   {ok, State :: term()} | {error, term()}.

Prepare the chosen system slot for update (e.g., unmount filesystem, ensure not the booted slot). Must not write object data. Return the updated State or an error to abort.

system_set_updated(State, SysId)

-callback system_set_updated(State :: term(), SysId :: system_id()) ->
                                {ok, State :: term()} | {error, term()}.

Record that the target system slot was updated successfully (e.g., set next-boot slot, write bootloader state) after all objects completed. Persist changes as needed and return updated State.

system_terminate(State, Reason)

-callback system_terminate(State :: term(), Reason :: term()) -> ok.

Termination hook for cleanup. Reason indicates shutdown or error cause.

system_update_cleanup(State)

(optional)
-callback system_update_cleanup(State :: term()) -> State :: term().

Guaranteed end-of-update cleanup. Called exactly once after the update attempt concludes when system_update_init/2 previously succeeded, regardless of outcome (success, failure, or cancel during updating). Return the updated State. Cleanup must be best-effort and not fail.

system_update_init(State, Info)

(optional)
-callback system_update_init(State :: term(), Info :: map()) -> {ok, State :: term()} | {error, term()}.

Called once the update manifest is loaded and before any object is written. Provides high-level firmware metadata (product, version, objects, etc.) so the HAL can persist or validate it and keep any data it needs in its State.

system_updated(State)

(optional)
-callback system_updated(State :: term()) -> {ok, State :: term()} | {error, term()}.

Called once the entire update succeeded (all objects).

system_validate(State)

-callback system_validate(State :: term()) -> {ok, State :: term()} | {error, term()}.

Validate the currently running system (e.g., clear update-pending flag, commit the active slot). Typically called on first boot after the update has been applied and verified.