Revert "Revert "[Feature][API-794]when a/b slot broken, rollback and repair it.-2.system partition rollback""

This reverts commit 3646d814962625eabe3d08fc34323929506fe265.

Reason for revert: <INSERT REASONING HERE>

Change-Id: I27bca8004386b66d474efacaa55c9151607e3e76
diff --git a/src/kernel/linux/v4.19/drivers/Makefile b/src/kernel/linux/v4.19/drivers/Makefile
index 6066d60..508c8da 100644
--- a/src/kernel/linux/v4.19/drivers/Makefile
+++ b/src/kernel/linux/v4.19/drivers/Makefile
@@ -84,6 +84,7 @@
 obj-$(CONFIG_ATA)		+= ata/
 obj-$(CONFIG_TARGET_CORE)	+= target/
 obj-$(CONFIG_MTD)		+= mtd/
+obj-y				+= lynq_bootctrl/
 obj-$(CONFIG_SPI)		+= spi/
 obj-$(CONFIG_SPMI)		+= spmi/
 obj-$(CONFIG_HSI)		+= hsi/
diff --git a/src/kernel/linux/v4.19/drivers/lynq_bootctrl/Makefile b/src/kernel/linux/v4.19/drivers/lynq_bootctrl/Makefile
new file mode 100755
index 0000000..19063c1
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/lynq_bootctrl/Makefile
@@ -0,0 +1,2 @@
+
+obj-y	+= lynq_bootctrl.o
diff --git a/src/kernel/linux/v4.19/drivers/lynq_bootctrl/lynq_bootctrl.c b/src/kernel/linux/v4.19/drivers/lynq_bootctrl/lynq_bootctrl.c
new file mode 100755
index 0000000..f7169a1
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/lynq_bootctrl/lynq_bootctrl.c
@@ -0,0 +1,186 @@
+#include <linux/init.h>

+#include <linux/kernel.h>

+#include <linux/module.h>

+#include <linux/of.h>

+#include <linux/fs.h>

+#include <linux/platform_device.h>

+#include <asm/uaccess.h>

+#include "lynq_bootctrl.h"

+#include <linux/string.h> 

+#include <linux/slab.h>

+#include <linux/mtd/mtd.h>

+

+int bootctrl_read_metadata(AvbABData *bctrl);

+int bootctrl_write_metadata(AvbABData *bctrl);

+

+const char *mtd_name = "misc";

+int current_slot = -1;

+int current_slot_init = 0;

+

+int bootctrl_write_metadata(AvbABData *bctrl)

+{

+    int err;

+    ssize_t sz, size;

+    char *buf = (char *)bctrl;

+    struct mtd_info *mtd = NULL;

+    loff_t pos = OFFSETOF_SLOT_SUFFIX;

+

+    if(bctrl == NULL)

+    {

+        printk("ERROR: null pointer");

+        return -1;

+    }

+    err = IS_ERR(bctrl);

+    if(err != 0)

+    {

+        printk("ERROR: pointer: %d.", err);

+        return err;

+    }

+    mtd = get_mtd_device_nm(mtd_name);

+    err = IS_ERR(mtd);

+    if(err != 0)

+    {

+        printk("ERROR: pointer: %d.", err);

+        return err;

+    }

+

+    size = sizeof(AvbABData);

+

+    do {

+        err = mtd_write(mtd, pos, size, &sz, buf);

+

+        if (err == 0) 

+        {

+            break;

+        }

+        else if (err < 0)

+        {

+            printk("Error Writing metadata file\n");

+            return err;

+        }

+        size -= sz;

+        buf += sz;

+    } while(size > 0);

+    printk("BOOTCTRL:write new info to metadata\n");

+    return 0;

+}

+

+int bootctrl_get_active_slot(void)

+{

+    int slot = 0, ret = -1;

+    AvbABData metadata;

+

+    ret = bootctrl_read_metadata(&metadata);

+    if(ret < 0)

+    {

+        printk("BOOTCTRL:read metadata error: %d", ret);

+    }

+    slot = (metadata.slots[0].priority >= metadata.slots[1].priority) ? 0 : 1;

+    printk("the slot is %d", slot);

+    return slot;

+}

+EXPORT_SYMBOL(bootctrl_get_active_slot);

+

+int bootctrl_read_metadata(AvbABData *bctrl)

+{

+    int ret, err;

+    loff_t pos = OFFSETOF_SLOT_SUFFIX;

+    size_t sz, size;

+    char *buf = (char *)bctrl;

+    struct mtd_info *mtd = NULL;

+

+    if(bctrl == NULL)

+    {

+        printk("ERROR: null pointer");

+        return -1;

+    }

+    err = IS_ERR(bctrl);

+    if(err != 0)

+    {

+        printk("ERROR: pointer: %d.", err);

+        printk("error: %ld", PTR_ERR(mtd));

+        return err;

+    }

+    mtd = get_mtd_device_nm(mtd_name);

+    ret = IS_ERR(mtd);

+    if(ret != 0)

+    {

+        printk("ERROR: pointer: %d.", ret);

+        printk("error: %ld", PTR_ERR(mtd));

+        return ret;

+    }

+

+    size = sizeof(AvbABData);

+    do {

+        ret = mtd_read(mtd, pos, size, &sz, buf);

+        if (sz == 0)

+        {

+            break;

+        }

+        else if (sz < 0)

+        {

+            printk("BOOTCTRL:Error reading metadata file: %ld\n", sz);

+            return sz;

+        }

+        size -= sz;

+        buf += sz;

+    } while(size > 0);

+

+    /* Check bootctrl magic number */

+    if (memcmp(bctrl->magic , AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0)

+    {

+        printk("BOOTCTRL:metadata is not initialised or corrupted %s.\n", bctrl->magic);

+        return -EIO;

+    }

+    return 0;

+}

+EXPORT_SYMBOL(bootctrl_read_metadata);

+

+int bootctrl_mark_boot_unsuccessful(void)

+{

+    int ret;

+    int slot = 0;

+    AvbABData metadata;

+    AvbABSlotData *slotp;

+

+    if(current_slot_init != 1)

+    {

+        printk("BOOTCTRL: current slot has not been init");

+        return 0;

+    }

+    printk("BOOTCTRL:boot control bootctrl_mark_boot_unsuccessful\n");

+    ret = bootctrl_read_metadata(&metadata);

+    if (ret < 0) 

+    {

+        printk("BOOTCTRL: read metadata error");

+        return ret;

+    }

+

+    slot = current_slot;

+

+    slotp = &metadata.slots[slot];

+    printk("BOOTCTRL: currentslot = %d, retry time = %u",slot, slotp->tries_remaining);

+    slotp->successful_boot = 0;

+

+    return bootctrl_write_metadata(&metadata);

+}

+EXPORT_SYMBOL(bootctrl_mark_boot_unsuccessful);

+

+static int __init drv_init(void)

+{

+    printk("BOOTCTRL: get current slot");

+    current_slot = bootctrl_get_active_slot();

+    if (current_slot < 0)

+    {

+        printk("bootctrl_get_active_slot fail , slot = %d\n", current_slot);

+        return current_slot;

+    }

+    current_slot_init = 1;

+    return 0;

+}

+

+module_init(drv_init);

+MODULE_AUTHOR("Mobiletek");

+MODULE_DESCRIPTION("driver for bootctrl");

+MODULE_LICENSE("GPL");

+

diff --git a/src/kernel/linux/v4.19/drivers/lynq_bootctrl/lynq_bootctrl.h b/src/kernel/linux/v4.19/drivers/lynq_bootctrl/lynq_bootctrl.h
new file mode 100755
index 0000000..5ca3ca6
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/lynq_bootctrl/lynq_bootctrl.h
@@ -0,0 +1,92 @@
+#define BOOTCTRL_SUFFIX_A           "_a"
+#define BOOTCTRL_SUFFIX_B           "_b"
+#define BOOT_CONTROL_VERSION    1
+
+#define BOOTCTRL_PROPERTY "ro.boot.slot_suffix"
+#define SLOT_SUFFIX_STR "androidboot.slot_suffix="
+#define COMMAND_LINE_PATH "/proc/cmdline"
+#define COMMAND_LINE_SIZE 2048
+
+/* AVB20 */
+/* Magic for the A/B struct when serialized. */
+#define AVB_AB_MAGIC "\0AB0"
+#define AVB_AB_MAGIC_LEN 4
+
+/* Versioning for the on-disk A/B metadata - keep in sync with avbtool. */
+#define AVB_AB_MAJOR_VERSION 1
+#define AVB_AB_MINOR_VERSION 0
+
+/* Size of AvbABData struct. */
+#define AVB_AB_DATA_SIZE 32
+
+/* Maximum values for slot data */
+#define AVB_AB_MAX_PRIORITY 15
+#define AVB_AB_MAX_TRIES_REMAINING 7
+
+#define BOOTDEV_TYPE_NAND 1
+#define BOOTDEV_TYPE_EMMC 2
+
+#define OFFSETOF_SLOT_SUFFIX 2048
+
+/* Struct used for recording per-slot metadata.
+ *
+ * When serialized, data is stored in network byte-order.
+ */
+typedef struct AvbABSlotData {
+  /* Slot priority. Valid values range from 0 to AVB_AB_MAX_PRIORITY,
+   * both inclusive with 1 being the lowest and AVB_AB_MAX_PRIORITY
+   * being the highest. The special value 0 is used to indicate the
+   * slot is unbootable.
+   */
+  uint8_t priority;
+
+  /* Number of times left attempting to boot this slot ranging from 0
+   * to AVB_AB_MAX_TRIES_REMAINING.
+   */
+  uint8_t tries_remaining;
+
+  /* Non-zero if this slot has booted successfully, 0 otherwise. */
+  uint8_t successful_boot;
+  /* For lk anti rollback*/
+  uint8_t efuse_write;
+  uint8_t bl_ver;
+  /* Reserved for future use. */
+  uint8_t reserved[3];
+
+} AvbABSlotData;
+
+/* Struct used for recording A/B metadata.
+ *
+ * When serialized, data is stored in network byte-order.
+ */
+typedef struct AvbABData {
+  /* Magic number used for identification - see AVB_AB_MAGIC. */
+  uint8_t magic[AVB_AB_MAGIC_LEN];
+
+  /* Version of on-disk struct - see AVB_AB_{MAJOR,MINOR}_VERSION. */
+  uint8_t version_major;
+  uint8_t version_minor;
+
+  /* Padding to ensure |slots| field start eight bytes in. */
+  uint8_t reserved1[2];
+
+  /* Per-slot metadata. */
+  AvbABSlotData slots[2];
+
+  /* Reserved for future use. */
+  uint8_t reserved2[12];
+
+  /* CRC32 of all 28 bytes preceding this field. */
+  uint32_t crc32;
+} AvbABData;
+//static struct fstab* fstab = NULL;
+
+
+
+int bootctrl_get_active_slot(void);
+
+int bootctrl_read_metadata(AvbABData *bctrl);
+
+int bootctrl_write_metadata(AvbABData *bctrl);
+
+int bootctrl_mark_boot_unsuccessful(void);
\ No newline at end of file
diff --git a/src/kernel/linux/v4.19/drivers/md/dm-verity-target.c b/src/kernel/linux/v4.19/drivers/md/dm-verity-target.c
index 758b802..9a422a9 100644
--- a/src/kernel/linux/v4.19/drivers/md/dm-verity-target.c
+++ b/src/kernel/linux/v4.19/drivers/md/dm-verity-target.c
@@ -16,6 +16,7 @@
 
 #include "dm-verity.h"
 #include "dm-verity-fec.h"
+#include "../lynq_bootctrl/lynq_bootctrl.h"
 
 #include <linux/module.h>
 #include <linux/reboot.h>
@@ -215,6 +216,7 @@
 	char verity_env[DM_VERITY_ENV_LENGTH];
 	char *envp[] = { verity_env, NULL };
 	const char *type_str = "";
+	int ret;
 	struct mapped_device *md = dm_table_get_md(v->ti->table);
 
 	/* Corruption should be visible in device status in all modes */
@@ -255,6 +257,14 @@
 #ifdef CONFIG_DM_VERITY_AVB
 		dm_verity_avb_error_handler();
 #endif
+//xf.li@20230313 modify for ab_rollback start
+		printk("BOOTCTRL:dm-verity error, rollback");
+		ret = bootctrl_mark_boot_unsuccessful();
+		if(ret != 0)
+		{
+			printk("BOOTCTRL:error rollback\n");
+		}
+//xf.li@20230313 modify for ab_rollback end
 		kernel_restart("dm-verity device corrupted");
 	}
 
diff --git a/src/kernel/linux/v4.19/init/do_mounts_dm.c b/src/kernel/linux/v4.19/init/do_mounts_dm.c
index cb63c62..6df0b4c 100644
--- a/src/kernel/linux/v4.19/init/do_mounts_dm.c
+++ b/src/kernel/linux/v4.19/init/do_mounts_dm.c
@@ -11,7 +11,7 @@
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/delay.h>
-
+#include "../drivers/lynq_bootctrl/lynq_bootctrl.h"
 #include "do_mounts.h"
 
 #define DM_MAX_DEVICES 256
@@ -373,6 +373,9 @@
 	}
 
 	if (!dm_dev) {
+//xf.li@20230313 modify for ab_rollback start
+		printk("BOOTCTRL:can't find dm_dev.\n");
+//xf.li@20230313 modify for ab_rollback end
 		ret = -ENODEV;
 		goto free_dm_params;
 	}
@@ -393,6 +396,7 @@
 	char *uuid;
 	fmode_t fmode = FMODE_READ;
 	struct dm_device *devices;
+	int ret;
 
 	devices = dm_parse_args();
 
@@ -425,7 +429,9 @@
 			       target->type, target->params);
 
 			if (dm_wait_for_drive(target->params))
+			{
 				goto add_target_fail;
+			}
 
 			if (dm_table_add_target(table, target->type,
 						target->begin,
@@ -501,6 +507,13 @@
 dm_create_fail:
 	DMWARN("starting dm-%d (%s) failed",
 	       dev->minor, dev->name);
+//xf.li@20230313 modify for ab_rollback start
+	ret = bootctrl_mark_boot_unsuccessful();
+	if(ret != 0)
+	{
+		printk("BOOTCTRL:error rollback\n");
+	}
+//xf.li@20230313 modify for ab_rollback end
 	dm_setup_cleanup(devices);
 }