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);
}