From dfc5ca4495315d293ccdb1c52d7d29a133ba596b Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Mon, 22 Jun 2020 14:32:45 +0200
Subject: [PATCH 09/43] base-files: make sysupgrade work on qcom AX

The qsdk v4.4 ubi layer does not detach the rootfs properly during
sysupgrade. Pull in the ubu force detach patch from owrt-15.05.

Signed-off-by: John Crispin <john@phrozen.org>
---
 package/base-files/files/lib/upgrade/nand.sh  |  14 +-
 .../patches/131-add_ubi_force_detach.patch    | 185 ++++++++++++++++++
 2 files changed, 195 insertions(+), 4 deletions(-)
 create mode 100644 package/utils/mtd-utils/patches/131-add_ubi_force_detach.patch

diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh
index e335d940ed..ab3db4cdf2 100644
--- a/package/base-files/files/lib/upgrade/nand.sh
+++ b/package/base-files/files/lib/upgrade/nand.sh
@@ -12,6 +12,9 @@ CI_UBIPART="${CI_UBIPART:-ubi}"
 # 'rootfs' UBI volume on NAND contains the rootfs
 CI_ROOTPART="${CI_ROOTPART:-rootfs}"
 
+# ipq807x qsdk kernel misbehaves
+CI_IPQ807X=0
+
 ubi_mknod() {
 	local dir="$1"
 	local dev="/dev/$(basename $dir)"
@@ -131,6 +134,8 @@ nand_upgrade_prepare_ubi() {
 		return 1
 	fi
 
+	[ "$CI_IPQ807X" = 1 ] && ubidetach -f -m $mtdnum
+
 	local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
 	if [ ! "$ubidev" ]; then
 		ubiattach -m "$mtdnum"
@@ -213,7 +218,6 @@ nand_upgrade_prepare_ubi() {
 
 nand_do_upgrade_success() {
 	local conf_tar="/tmp/sysupgrade.tgz"
-
 	sync
 	[ -f "$conf_tar" ] && nand_restore_config "$conf_tar"
 	echo "sysupgrade successful"
@@ -292,10 +296,12 @@ nand_upgrade_tar() {
 	local has_kernel=1
 	local has_env=0
 
-	[ "$kernel_length" != 0 -a -n "$kernel_mtd" ] && {
-		tar xf "$tar_file" ${board_dir}/kernel -O | mtd write - $CI_KERNPART
+	[ "$CI_IPQ807X" = 0 -a "$kernel_length" != 0 -a -n "$kernel_mtd" ] && {
+		tar xf $tar_file ${board_dir}/kernel -O | mtd write - $CI_KERNPART
+	}
+	[ "$CI_IPQ807X" = 0 ] && {
+		[ "$kernel_length" = 0 -o ! -z "$kernel_mtd" ] && has_kernel=
 	}
-	[ "$kernel_length" = 0 -o ! -z "$kernel_mtd" ] && has_kernel=
 
 	nand_upgrade_prepare_ubi "$rootfs_length" "$rootfs_type" "${has_kernel:+$kernel_length}" "$has_env"
 
diff --git a/package/utils/mtd-utils/patches/131-add_ubi_force_detach.patch b/package/utils/mtd-utils/patches/131-add_ubi_force_detach.patch
new file mode 100644
index 0000000000..f3cd6a6b28
--- /dev/null
+++ b/package/utils/mtd-utils/patches/131-add_ubi_force_detach.patch
@@ -0,0 +1,185 @@
+--- a/include/mtd/ubi-user.h
++++ b/include/mtd/ubi-user.h
+@@ -176,6 +176,7 @@
+ #define UBI_IOCATT _IOW(UBI_CTRL_IOC_MAGIC, 64, struct ubi_attach_req)
+ /* Detach an MTD device */
+ #define UBI_IOCDET _IOW(UBI_CTRL_IOC_MAGIC, 65, int32_t)
++#define UBI_IOCFDET _IOW(UBI_CTRL_IOC_MAGIC, 99, int32_t)
+ 
+ /* ioctl commands of UBI volume character devices */
+ 
+--- a/include/libubi.h
++++ b/include/libubi.h
+@@ -48,6 +48,7 @@ typedef void * libubi_t;
+  *           number)
+  * @mtd_num: MTD device number to attach (used if @mtd_dev_node is %NULL)
+  * @mtd_dev_node: path to MTD device node to attach
++ * @force: set if the device should be removed even if it's busy
+  * @vid_hdr_offset: VID header offset (%0 means default offset and this is what
+  *                  most of the users want)
+  * @max_beb_per1024: Maximum expected bad eraseblocks per 1024 eraseblocks
+@@ -240,29 +241,33 @@ int ubi_attach(libubi_t desc, const char
+  * corresponding UBI device is removed. Returns zero in case of success and %-1
+  * in case of failure.
+  */
+-int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num);
++int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num, int force);
+ 
+ /**
+  * ubi_detach - detach an MTD device by its node path.
+  * @desc: UBI library descriptor
+  * @node: name of the UBI control character device node
+  * @mtd_dev_node: path to an MTD device node
++ * @force: set if the device should be removed even if it's busy
+  *
+  * This function detaches an MTD device @mtd_dev_node from UBI. Returns zero in
+  * case of success and %-1 in case of failure.
+  */
+-int ubi_detach(libubi_t desc, const char *node, const char *mtd_dev_node);
++int ubi_detach(libubi_t desc, const char *node, const char *mtd_dev_node,
++	int force);
+ 
+ /**
+  * ubi_remove_dev - remove an UBI device.
+  * @desc: UBI library descriptor
+  * @node: name of the UBI control character device node
+  * @ubi_dev: UBI device number to remove
++ * @force: set if the device should be removed even if it's busy
+  *
+  * This function removes UBI device number @ubi_dev and returns zero in case of
+  * success and %-1 in case of failure.
+  */
+-int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev);
++int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev,
++	int force);
+ 
+ /**
+  * ubi_mkvol - create an UBI volume.
+--- a/lib/libubi.c
++++ b/lib/libubi.c
+@@ -808,7 +808,7 @@ int ubi_attach(libubi_t desc, const char
+ 	return ret;
+ }
+ 
+-int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num)
++int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num, int force)
+ {
+ 	int ret, ubi_dev;
+ 
+@@ -818,10 +818,11 @@ int ubi_detach_mtd(libubi_t desc, const
+ 		return ret;
+ 	}
+ 
+-	return ubi_remove_dev(desc, node, ubi_dev);
++	return ubi_remove_dev(desc, node, ubi_dev, force);
+ }
+ 
+-int ubi_detach(libubi_t desc, const char *node, const char *mtd_dev_node)
++int ubi_detach(libubi_t desc, const char *node, const char *mtd_dev_node,
++	int force)
+ {
+ 	int mtd_num;
+ 
+@@ -834,10 +835,10 @@ int ubi_detach(libubi_t desc, const char
+ 	if (mtd_num == -1)
+ 		return -1;
+ 
+-	return ubi_detach_mtd(desc, node, mtd_num);
++	return ubi_detach_mtd(desc, node, mtd_num, force);
+ }
+ 
+-int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev)
++int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev, int force)
+ {
+ 	int fd, ret;
+ 
+@@ -847,6 +848,10 @@ int ubi_remove_dev(libubi_t desc, const
+ 	if (fd == -1)
+ 		return sys_errmsg("cannot open \"%s\"", node);
+ 	ret = ioctl(fd, UBI_IOCDET, &ubi_dev);
++	if (force)
++		ret = ioctl(fd, UBI_IOCFDET, &ubi_dev);
++	else
++		ret = ioctl(fd, UBI_IOCDET, &ubi_dev);
+ 	if (ret == -1)
+ 		goto out_close;
+ 
+--- a/ubi-utils/ubidetach.c
++++ b/ubi-utils/ubidetach.c
+@@ -40,6 +40,7 @@ struct args {
+ 	int mtdn;
+ 	const char *node;
+ 	const char *dev;
++	int force;
+ };
+ 
+ static struct args args = {
+@@ -47,6 +48,7 @@ static struct args args = {
+ 	.mtdn = -1,
+ 	.node = NULL,
+ 	.dev = NULL,
++	.force = 0,
+ };
+ 
+ static const char doc[] = PROGRAM_NAME " version " VERSION
+@@ -56,13 +58,14 @@ static const char optionsstr[] =
+ "-d, --devn=<UBI device number>  UBI device number to delete\n"
+ "-p, --dev-path=<path to device> or alternatively, MTD device node path to detach\n"
+ "-m, --mtdn=<MTD device number>  or alternatively, MTD device number to detach\n"
++"-f, --force			 Force UBI detach even if it is still busy\n"
+ "-h, --help                      print help message\n"
+ "-V, --version                   print program version";
+ 
+ static const char usage[] =
+ "Usage: " PROGRAM_NAME " [<UBI control device node file name>]\n"
+ "\t[-d <UBI device number>] [-m <MTD device number>] [-p <path to device>]\n"
+-"\t[--devn=<UBI device number>] [--mtdn=<MTD device number>]\n"
++"\t[--devn=<UBI device number>] [--mtdn=<MTD device number>] [-f]\n"
+ "\t[--dev-path=<path to device>]\n"
+ "UBI control device defaults to " DEFAULT_CTRL_DEV " if not supplied.\n"
+ "Example 1: " PROGRAM_NAME " -p /dev/mtd0 - detach MTD device /dev/mtd0\n"
+@@ -83,7 +86,7 @@ static int parse_opt(int argc, char * co
+ 	while (1) {
+ 		int key, error = 0;
+ 
+-		key = getopt_long(argc, argv, "p:m:d:hV", long_options, NULL);
++		key = getopt_long(argc, argv, "p:m:d:fhV", long_options, NULL);
+ 		if (key == -1)
+ 			break;
+ 
+@@ -104,6 +107,9 @@ static int parse_opt(int argc, char * co
+ 				return errmsg("bad MTD device number: \"%s\"", optarg);
+ 
+ 			break;
++		case 'f':
++			args.force = 1;
++			break;
+ 
+ 		case 'h':
+ 			printf("%s\n\n", doc);
+@@ -176,20 +182,22 @@ int main(int argc, char * const argv[])
+ 	}
+ 
+ 	if (args.devn != -1) {
+-		err = ubi_remove_dev(libubi, args.node, args.devn);
++		err = ubi_remove_dev(libubi, args.node, args.devn, args.force);
+ 		if (err) {
+ 			sys_errmsg("cannot remove ubi%d", args.devn);
+ 			goto out_libubi;
+ 		}
+ 	} else {
+ 		if (args.dev != NULL) {
+-			err = ubi_detach(libubi, args.node, args.dev);
++			err = ubi_detach(libubi, args.node, args.dev,
++					args.force);
+ 			if (err) {
+ 				sys_errmsg("cannot detach \"%s\"", args.dev);
+ 				goto out_libubi;
+ 			}
+ 		} else {
+-			err = ubi_detach_mtd(libubi, args.node, args.mtdn);
++			err = ubi_detach_mtd(libubi, args.node, args.mtdn,
++					     args.force);
+ 			if (err) {
+ 				sys_errmsg("cannot detach mtd%d", args.mtdn);
+ 				goto out_libubi;
-- 
2.25.1

