@@ -20,4 +20,5 @@ lib-$(CONFIG_JSON) += parsing_library_libjson.o
lib-$(CONFIG_CHANNEL_CURL) += channel_curl.o
lib-$(CONFIG_SIGALG_RAWRSA) += swupdate_rsa_verify.o
lib-$(CONFIG_SIGALG_CMS) += swupdate_cms_verify.o
+lib-$(CONFIG_UBIVOL) += ubi_interface.o
@@ -32,6 +32,7 @@
#include "parsers.h"
#include "bootloader.h"
#include "progress.h"
+#include "ubi_util.h"
/*
* function returns:
@@ -353,6 +354,14 @@ int install_images(struct swupdate_cfg *sw, int fdsw, int fromfile)
return ret;
}
+#ifdef CONFIG_UBIVOL
+ ret = run_ubi_swap(sw);
+ if (ret) {
+ ERROR("execute ubi swap failed");
+ return ret;
+ }
+#endif
+
ret = run_prepost_scripts(&sw->scripts, POSTINSTALL);
if (ret) {
ERROR("execute postinstall scripts failed");
new file mode 100644
@@ -0,0 +1,208 @@
+/*
+ * (C) Copyright 2019
+ * Philippe Reynes <philippe.reynes@softathome.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include <mtd/mtd-user.h>
+
+#include "flash.h"
+#include "util.h"
+#include "ubi_util.h"
+
+struct ubirnvol {
+ int dev_num;
+ char masternode[SWUPDATE_GENERAL_STRING_SIZE];
+ struct ubi_rnvol_req rnvol;
+ LIST_ENTRY(ubirnvol) next;
+};
+
+LIST_HEAD(ubirnvollist, ubirnvol);
+
+static void init_ubirnvollist(struct ubirnvollist *list)
+{
+ LIST_INIT(list);
+}
+
+static void free_ubirnvollist(struct ubirnvollist *list)
+{
+ struct ubirnvol *ubirnvol, *ubirnvol_tmp;
+
+ LIST_FOREACH_SAFE(ubirnvol, list, next, ubirnvol_tmp) {
+ LIST_REMOVE(ubirnvol, next);
+ free(ubirnvol);
+ }
+}
+
+static struct ubirnvol *search_ubirnvol(struct ubirnvollist *list, int dev_num)
+{
+ struct ubirnvol *rnvol;
+
+ LIST_FOREACH(rnvol, list, next) {
+ if (rnvol->dev_num == dev_num)
+ return rnvol;
+ }
+
+ return NULL;
+}
+
+static int fill_ubirnvol(struct ubirnvol *ubirnvol,
+ struct ubi_part *old_ubi_part,
+ struct ubi_part *new_ubi_part)
+{
+ int old_dev_num, old_vol_id;
+ int new_dev_num, new_vol_id;
+ char *old_name, *new_name;
+ struct ubi_rnvol_req *rnvol;
+ int num_swap;
+
+ if (!ubirnvol || !old_ubi_part || !new_ubi_part)
+ return -1;
+
+ old_dev_num = old_ubi_part->vol_info.dev_num;
+ old_vol_id = old_ubi_part->vol_info.vol_id;
+ old_name = &old_ubi_part->vol_info.name[0];
+
+ new_dev_num = new_ubi_part->vol_info.dev_num;
+ new_vol_id = new_ubi_part->vol_info.vol_id;
+ new_name = &new_ubi_part->vol_info.name[0];
+
+ rnvol = &ubirnvol->rnvol;
+ num_swap = rnvol->count;
+
+ if ((ubirnvol->dev_num != old_dev_num) || (old_dev_num != new_dev_num))
+ return -1;
+
+ rnvol->ents[num_swap + 0].vol_id = old_vol_id;
+ rnvol->ents[num_swap + 0].name_len = strlen(new_name);
+ strcpy(&rnvol->ents[num_swap + 0].name[0], new_name);
+
+ rnvol->ents[num_swap + 1].vol_id = new_vol_id;
+ rnvol->ents[num_swap + 1].name_len = strlen(old_name);
+ strcpy(&rnvol->ents[num_swap + 1].name[0], old_name);
+
+ rnvol->count += 2;
+
+ return 0;
+}
+
+static struct ubirnvol *create_ubirnvol(struct ubi_part *old_ubi_part,
+ struct ubi_part *new_ubi_part)
+{
+ struct ubirnvol *ubirnvol;
+ int ret;
+
+ ubirnvol = (struct ubirnvol *)calloc(1, sizeof(*ubirnvol));
+ if (!ubirnvol)
+ goto out;
+
+ ubirnvol->dev_num = old_ubi_part->vol_info.dev_num;
+ snprintf(&ubirnvol->masternode[0], sizeof(ubirnvol->masternode),
+ "/dev/ubi%d", old_ubi_part->vol_info.dev_num);
+
+ ret = fill_ubirnvol(ubirnvol, old_ubi_part, new_ubi_part);
+ if (ret) {
+ free(ubirnvol);
+ ubirnvol = NULL;
+ }
+
+ out:
+ return ubirnvol;
+}
+
+static int run_ubirnvol(struct ubirnvollist *list)
+{
+ struct flash_description *flash = get_flash_info();
+ libubi_t libubi = flash->libubi;
+ struct ubirnvol *ubirnvol;
+ int ret = 0;
+
+ LIST_FOREACH(ubirnvol, list, next) {
+ ret = ubi_rnvols(libubi, ubirnvol->masternode, &ubirnvol->rnvol);
+ if (ret < 0)
+ break;
+ }
+
+ return ret;
+}
+
+static struct ubi_part *search_volume(const char *str, struct ubilist *list)
+{
+ struct ubi_part *vol;
+
+ LIST_FOREACH(vol, list, next) {
+ if (strcmp(vol->vol_info.name, str) == 0)
+ return vol;
+ }
+ return NULL;
+}
+
+static struct ubi_part *search_volume_global(const char *str)
+{
+ struct flash_description *flash = get_flash_info();
+ struct mtd_info *mtd_info = &flash->mtd;
+ struct mtd_ubi_info *mtd_ubi_info;
+ struct ubi_part *ubivol;
+ int i;
+
+ for (i = mtd_info->lowest_mtd_num; i <= mtd_info->highest_mtd_num; i++) {
+ mtd_ubi_info = &flash->mtd_info[i];
+ ubivol = search_volume(str, &mtd_ubi_info->ubi_partitions);
+ if (ubivol)
+ return ubivol;
+ }
+ return NULL;
+}
+
+int run_ubi_swap(struct swupdate_cfg *sw)
+{
+ struct ubirnvollist ubirnvollist;
+ struct img_type *img;
+ struct ubi_part *old_ubi_part, *new_ubi_part;
+ int ret, dev_num = -1;
+
+ init_ubirnvollist(&ubirnvollist);
+
+ LIST_FOREACH(img, &sw->images, next) {
+ char *tmpvol_name;
+ struct ubirnvol *ubirnvol;
+
+ tmpvol_name = dict_get_value(&img->properties, "atomic-replaces");
+ if (tmpvol_name) {
+ TRACE("atomic-replaces: will swap UBI volume %s <-> %s", img->volname, tmpvol_name);
+
+ old_ubi_part = search_volume_global(img->volname);
+ new_ubi_part = search_volume_global(tmpvol_name);
+
+ dev_num = old_ubi_part->vol_info.dev_num;
+
+ ubirnvol = search_ubirnvol(&ubirnvollist, dev_num);
+ if (ubirnvol) {
+ ret = fill_ubirnvol(ubirnvol, old_ubi_part, new_ubi_part);
+ if (ret)
+ goto out;
+ } else {
+ ubirnvol = create_ubirnvol(old_ubi_part, new_ubi_part);
+ if (!ubirnvol) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ LIST_INSERT_HEAD(&ubirnvollist, ubirnvol, next);
+ }
+ }
+ }
+
+ ret = run_ubirnvol(&ubirnvollist);
+
+ out:
+ free_ubirnvollist(&ubirnvollist);
+
+ return ret;
+}
new file mode 100644
@@ -0,0 +1,15 @@
+/*
+ * (C) Copyright 2019
+ * Philippe Reynes <philippe.reynes@softathome.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef _UBI_UTIL_H
+#define _UBI_UTIL_H
+
+#include "swupdate.h"
+
+int run_ubi_swap(struct swupdate_cfg *sw);
+
+#endif
Signed-off-by: Philippe Reynes <philippe.reynes@softathome.com> --- corelib/Makefile | 1 + corelib/installer.c | 9 +++ corelib/ubi_interface.c | 208 ++++++++++++++++++++++++++++++++++++++++++++++++ include/ubi_util.h | 15 ++++ 4 files changed, 233 insertions(+) create mode 100644 corelib/ubi_interface.c create mode 100644 include/ubi_util.h