diff --git a/common/bootchooser.c b/common/bootchooser.c index 29f61ae..c47c734 100644 --- a/common/bootchooser.c +++ b/common/bootchooser.c @@ -57,6 +57,7 @@ struct state *state; char *state_prefix; + int refs; int verbose; int dryrun; @@ -344,11 +345,15 @@ bootchooser_target_set_priority(target, -1); } +static struct bootchooser *bootchooser; + /** - * bootchooser_get - get a bootchooser instance + * bootchooser_get - get a reference to the bootchooser * - * This evaluates the different globalvars and eventually state variables, - * creates a bootchooser instance from it and returns it. + * When no bootchooser is initialized this function allocates the bootchooser + * and initializes it with the different globalvars and state variables. The + * bootchooser is returned. Subsequent calls will return a reference to the same + * bootchooser. */ struct bootchooser *bootchooser_get(void) { @@ -359,6 +364,11 @@ uint32_t last_chosen; static int attempts_resetted; + if (bootchooser) { + bootchooser->refs++; + return bootchooser; + } + bc = xzalloc(sizeof(*bc)); if (*state_prefix) { @@ -473,6 +483,10 @@ } + bootchooser = bc; + + bootchooser->refs = 1; + return bc; err: @@ -528,16 +542,26 @@ } /** - * bootchooser_put - release a bootchooser instance + * bootchooser_put - return a bootchooser reference * @bc: The bootchooser instance * - * This releases a bootchooser instance and the memory associated with it. + * This returns a reference to the bootchooser. If it is the last reference the + * bootchooser is saved and the associated memory is freed. + * + * Return: 0 for success or a negative error code. An error can occur when + * bootchooser_save fails to write to the storage, nevertheless the + * bootchooser reference is still released. */ int bootchooser_put(struct bootchooser *bc) { struct bootchooser_target *target, *tmp; int ret; + bc->refs--; + + if (bc->refs) + return 0; + ret = bootchooser_save(bc); if (ret) pr_err("Failed to save bootchooser state: %s\n", strerror(-ret)); @@ -552,6 +576,8 @@ free(bc); + bootchooser = NULL; + return ret; }