From: Frieder Schrempf <[email protected]>
The RAUC bootmeth loads the boot script when booting, not when reading
the bootflow. If the boot fails, the bootflow keeps its private data and
can be booted again, for example with another 'bootflow boot'. Each
attempt then loads the script into a new buffer and adds another image
to the bootflow, but the previous buffer, image list entry and subdir
are never freed. 'bootstd images' lists one more copy of boot.scr after
every attempt.
If the previous attempt found the script but failed to read it, the
bootflow also stays in BOOTFLOWST_FILE. The next attempt then skips the
search and reads the file name and size found on the previous slot from
the partition of the new one.
Free what a previous attempt loaded and reset the state before loading
the script again. Move the freeing of the image list from bootflow_free()
into a new helper bootflow_free_images(), so that both can use it. Also
check the strdup() of the subdir.
Fixes: 7e5c2c782fb9 ("bootstd: Add implementation for bootmeth rauc")
Assisted-by: LLM
Signed-off-by: Frieder Schrempf <[email protected]>
---
Changes in v2:
- Reset the bootflow state before loading the script again (Simon)
- Move freeing the image list into bootflow_free_images() in
bootflow.c, used by bootflow_free() as well (Simon)
- Update the commit message accordingly
---
boot/bootflow.c | 13 +++++++++----
boot/bootmeth_rauc.c | 10 ++++++++++
include/bootflow.h | 10 ++++++++++
3 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/boot/bootflow.c b/boot/bootflow.c
index 7ee940460af..38747d35c29 100644
--- a/boot/bootflow.c
+++ b/boot/bootflow.c
@@ -634,10 +634,17 @@ void bootflow_init(struct bootflow *bflow, struct udevice
*bootdev,
alist_init_struct(&bflow->images, struct bootflow_img);
}
-void bootflow_free(struct bootflow *bflow)
+void bootflow_free_images(struct bootflow *bflow)
{
struct bootflow_img *img;
+ alist_for_each(img, &bflow->images)
+ free(img->fname);
+ alist_empty(&bflow->images);
+}
+
+void bootflow_free(struct bootflow *bflow)
+{
free(bflow->name);
free(bflow->subdir);
free(bflow->fname);
@@ -647,9 +654,7 @@ void bootflow_free(struct bootflow *bflow)
free(bflow->fdt_fname);
free(bflow->bootmeth_priv);
- alist_for_each(img, &bflow->images)
- free(img->fname);
- alist_empty(&bflow->images);
+ bootflow_free_images(bflow);
}
void bootflow_remove(struct bootflow *bflow)
diff --git a/boot/bootmeth_rauc.c b/boot/bootmeth_rauc.c
index 32e1de886cc..52d5be388cc 100644
--- a/boot/bootmeth_rauc.c
+++ b/boot/bootmeth_rauc.c
@@ -309,6 +309,14 @@ static int distro_rauc_load_boot_script(struct bootflow
*bflow,
if (!bflow->part)
return log_msg_ret("part", -ENOENT);
+ /* Drop the boot script of a previous, failed boot attempt */
+ free(bflow->buf);
+ bflow->buf = NULL;
+ free(bflow->subdir);
+ bflow->subdir = NULL;
+ bootflow_free_images(bflow);
+ bflow->state = BOOTFLOWST_READY;
+
ret = bootmeth_setup_fs(bflow, desc);
if (ret)
return log_msg_ret("set", ret);
@@ -320,6 +328,8 @@ static int distro_rauc_load_boot_script(struct bootflow
*bflow,
prefixes[i], script_names[j],
bflow->dev->name, bflow->part);
bflow->subdir = strdup(prefixes[i]);
+ if (!bflow->subdir)
+ return log_msg_ret("buf", -ENOMEM);
}
}
}
diff --git a/include/bootflow.h b/include/bootflow.h
index 1cfdda403ac..3df022f9aa3 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -395,6 +395,16 @@ int bootflow_first_glob(struct bootflow **bflowp);
*/
int bootflow_next_glob(struct bootflow **bflowp);
+/**
+ * bootflow_free_images() - Free the list of images of a bootflow
+ *
+ * This frees the file names of the images and empties the list. It does not
+ * free the image data itself.
+ *
+ * @bflow: Bootflow to update
+ */
+void bootflow_free_images(struct bootflow *bflow);
+
/**
* bootflow_free() - Free memory used by a bootflow
*
--
2.56.0