ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/package/utils/fitblk/Makefile b/package/utils/fitblk/Makefile
new file mode 100644
index 0000000..325963d
--- /dev/null
+++ b/package/utils/fitblk/Makefile
@@ -0,0 +1,42 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=fitblk
+PKG_RELEASE:=2
+PKG_LICENSE:=GPL-2.0-only
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+PKG_FLAGS:=nonshared
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/fitblk
+  HIDDEN:=1
+  SECTION:=base
+  CATEGORY:=Base system
+  TITLE:=fitblk firmware release tool
+endef
+
+define Package/fitblk/description
+Release uImage.FIT block devices using ioctl.
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		CC="$(TARGET_CC)" \
+		CFLAGS="$(TARGET_CFLAGS) -Wall -Werror" \
+		LDFLAGS="$(TARGET_LDFLAGS)"
+endef
+
+define Package/fitblk/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/fitblk $(1)/usr/sbin/
+	$(INSTALL_DIR) $(1)/lib/upgrade
+	$(INSTALL_DATA) ./files/fit.sh $(1)/lib/upgrade
+endef
+
+$(eval $(call BuildPackage,fitblk))
diff --git a/package/utils/fitblk/files/fit.sh b/package/utils/fitblk/files/fit.sh
new file mode 100644
index 0000000..b715a15
--- /dev/null
+++ b/package/utils/fitblk/files/fit.sh
@@ -0,0 +1,63 @@
+export_fitblk_bootdev() {
+	[ -e /sys/firmware/devicetree/base/chosen/rootdisk ] || return
+
+	local rootdisk="$(cat /sys/firmware/devicetree/base/chosen/rootdisk)"
+	local handle bootdev
+
+	for handle in /sys/class/mtd/mtd*/of_node/volumes/*/phandle; do
+		[ ! -e "$handle" ] && continue
+		if [ "$rootdisk" = "$(cat "$handle")" ]; then
+			if [ -e "${handle%/phandle}/volname" ]; then
+				export CI_KERNPART="$(cat "${handle%/phandle}/volname")"
+			elif [ -e "${handle%/phandle}/volid" ]; then
+				export CI_KERNVOLID="$(cat "${handle%/phandle}/volid")"
+			else
+				return
+			fi
+			export CI_UBIPART="$(cat "${handle%%/of_node*}/name")"
+			export CI_METHOD="ubi"
+			return
+		fi
+	done
+
+	for handle in /sys/class/mtd/mtd*/of_node/phandle; do
+		[ ! -e "$handle" ] && continue
+		if [ "$rootdisk" = "$(cat $handle)" ]; then
+			bootdev="${handle%/of_node/phandle}"
+			bootdev="${bootdev#/sys/class/mtd/}"
+			export PART_NAME="/dev/$bootdev"
+			export CI_METHOD="default"
+			return
+		fi
+	done
+
+	for handle in /sys/class/block/*/of_node/phandle; do
+		[ ! -e "$handle" ] && continue
+		if [ "$rootdisk" = "$(cat $handle)" ]; then
+			bootdev="${handle%/of_node/phandle}"
+			bootdev="${bootdev#/sys/class/block/}"
+			export EMMC_KERN_DEV="/dev/$bootdev"
+			export CI_METHOD="emmc"
+			return
+		fi
+	done
+}
+
+fit_do_upgrade() {
+	export_fitblk_bootdev
+	[ -n "$CI_METHOD" ] || return 1
+	[ -e /dev/fit0 ] && fitblk /dev/fit0
+	[ -e /dev/fitrw ] && fitblk /dev/fitrw
+
+	case "$CI_METHOD" in
+	emmc)
+		emmc_do_upgrade "$1"
+		;;
+	default)
+		default_do_upgrade "$1"
+		;;
+	ubi)
+		nand_do_upgrade "$1"
+		;;
+	esac
+}
diff --git a/package/utils/fitblk/src/Makefile b/package/utils/fitblk/src/Makefile
new file mode 100644
index 0000000..064764c
--- /dev/null
+++ b/package/utils/fitblk/src/Makefile
@@ -0,0 +1,7 @@
+all: fitblk
+
+fitblk:
+	$(CC) $(CFLAGS) -o $@ fitblk.c $(LDFLAGS)
+
+clean:
+	rm -f fitblk
diff --git a/package/utils/fitblk/src/fitblk.c b/package/utils/fitblk/src/fitblk.c
new file mode 100644
index 0000000..059ba60
--- /dev/null
+++ b/package/utils/fitblk/src/fitblk.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/fitblk.h>
+
+static int fitblk_release(char *device)
+{
+	int fd, ret;
+
+	fd = open(device, O_RDONLY);
+	if (fd == -1)
+		return errno;
+
+	ret = ioctl(fd, FITBLK_RELEASE, NULL);
+	close(fd);
+
+	if (ret == -1)
+		return errno;
+
+	return 0;
+}
+
+int main(int argc, char *argp[])
+{
+	int ret;
+
+	if (argc != 2) {
+		fprintf(stderr, "Release uImage.FIT sub-image block device\n");
+		fprintf(stderr, "Syntax: %s /dev/fitXXX\n", argp[0]);
+		return -EINVAL;
+	}
+
+	ret = fitblk_release(argp[1]);
+	if (ret)
+		fprintf(stderr, "fitblk: error releasing %s: %s\n", argp[1],
+			strerror(ret));
+	else
+		fprintf(stderr, "fitblk: %s released\n", argp[1]);
+
+	return ret;
+}