From: Petr Hodina <[email protected]>

Qualcomm devices don't use the bootloader_control block in "misc". The
slot active/unbootable state lives in the attribute flags (top 16 bits)
of each "boot_a"/"boot_b" GPT partition entry instead.

Make ab_select_slot() read those flags on CONFIG_ARCH_SNAPDRAGON.

Signed-off-by: Petr Hodina <[email protected]>
---
 boot/android_ab.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/boot/android_ab.c b/boot/android_ab.c
index f2b1110aa24..aedeb1edf28 100644
--- a/boot/android_ab.c
+++ b/boot/android_ab.c
@@ -191,9 +191,51 @@ static int ab_compare_slots(const struct slot_metadata *a,
        return 0;
 }
 
+/*
+ * Qualcomm devices don't use the bootloader_control_block in "misc" at all.
+ * Slot active/successful/unbootable state is stored directly in the top 16
+ * bits of each "boot_a"/"boot_b" GPT partition entry's own attribute flags.
+ */
+#define QCOM_AB_ATTR_SLOT_ACTIVE       (0x1 << 2)
+/* Not queried below, that is SBL's call */
+#define QCOM_AB_ATTR_BOOT_SUCCESSFUL   (0x1 << 6)
+#define QCOM_AB_ATTR_UNBOOTABLE                (0x1 << 7)
+
+static int qcom_gpt_select_slot(struct blk_desc *dev_desc)
+{
+       static const char * const names[] = { "boot_a", "boot_b" };
+       struct disk_partition part;
+       int slot = -1, i;
+
+       for (i = 0; i < ARRAY_SIZE(names); i++) {
+               if (part_get_info_by_name(dev_desc, names[i], &part) < 0)
+                       continue;
+               if (part.type_flags & QCOM_AB_ATTR_SLOT_ACTIVE) {
+                       slot = i;
+                       break;
+               }
+       }
+
+       if (slot < 0) {
+               log_err("qcom A/B: no slot marked active in the GPT\n");
+               return -ENODEV;
+       }
+
+       if (part.type_flags & QCOM_AB_ATTR_UNBOOTABLE) {
+               log_err("qcom A/B: active slot %c is marked unbootable\n",
+                       BOOT_SLOT_NAME(slot));
+               return -ENODEV;
+       }
+
+       return slot;
+}
+
 int ab_select_slot(struct blk_desc *dev_desc, struct disk_partition *part_info,
                   bool dec_tries)
 {
+       if (IS_ENABLED(CONFIG_ARCH_SNAPDRAGON))
+               return qcom_gpt_select_slot(dev_desc);
+
        struct bootloader_control *abc = NULL;
        struct bootloader_control *backup_abc = NULL;
        u32 crc32_le;

-- 
2.55.0


Reply via email to