A/B system updates use two sets of partitions referred to as slots (normally slot A and slot B). The system runs from the current slot while the partitions in the unused slot are not accessed by the running system during normal operation.
Each slot has a bootable attribute that states whether the slot contains a correct system from which the device can boot.
Each slot also has a successful attribute set by the user space, which is relevant only if the slot is also bootable. A successful slot should be able to boot, run, and update itself. A bootable slot that was not marked as successful (after several attempts were made to boot from it) should be marked as unbootable by the bootloader, including changing the active slot to another bootable slot (normally to the slot running immediately before the attempt to boot into the new, active one).
/* We iterate through the parition entries list, to find the partition with active slot suffix. */ for (n = 0; n < partition_count; n++) { if (!strncmp((constchar*)name, (constchar *)partition_entries[n].name, input_string_length)) { curr_suffix = (char *)(partition_entries[n].name+input_string_length);
/* if partition_entries.name is NULL terminated return the index */ if (*curr_suffix == '\0') return n; // tj: 完全一致名称
if (partition_multislot_is_supported()) { curr_slot = partition_find_active_slot();
/* If suffix string matches with current active slot suffix return index */ if (curr_slot != INVALID) { suffix_curr_actv_slot = SUFFIX_SLOT(curr_slot); if (!strncmp((constchar *)curr_suffix, suffix_curr_actv_slot, strlen(suffix_curr_actv_slot))) return n; else continue; } else { /* No valid active slot */ return INVALID_PTN; } } } } return INVALID_PTN; }
/* This function returns the most priority and active slot, also you need to update the global state seperately. */ intpartition_find_active_slot() { ... for (boot_priority = MAX_PRIORITY; boot_priority > 0; boot_priority--) { /* Search valid boot slot with highest priority */ for (i = 0; i < AB_SUPPORTED_SLOTS; i++) { current_priority = slot_priority(partition_entries, boot_slot_index[i]); current_active_bit = slot_is_active(partition_entries, boot_slot_index[i]); current_bootable_bit = slot_is_bootable(partition_entries, boot_slot_index[i]);
/* Count number of slots with all attributes as zero */ if ( !current_priority && !current_active_bit && current_bootable_bit) { count ++; continue; }
如上,忽略non active, non bootable, non priority的slot,对首次烧录都是non的给个default: SLOT_A。
/* All slots are zeroed, this is first bootup */ /* Marking and trying SLOT 0 as default */ if (count == AB_SUPPORTED_SLOTS) { /* Update the priority of the boot slot */ partition_activate_slot(SLOT_A);
active_slot = SLOT_A;
/* This is required to mark all bits as active, for fresh boot post fresh flash */ mark_all_partitions_active(active_slot); goto out; }
if (!strncmp(pname, "boot", strlen("boot")) || !strcmp(pname, "recovery")) { if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { fastboot_fail("image is not a boot image"); return-1; }
/* Reset multislot_partition attributes in case of flashing boot */ if (partition_multislot_is_supported()) { partition_reset_attributes(index); } }
注释写的很清楚,如果要烧boot,就要复位这个active slot分区的属性:
/* Function: To reset partition attributes This function reset partition_priority, retry_count and clear successful and bootable bits. */ voidpartition_reset_attributes(unsigned index) { structpartition_entry *partition_entries = partition_get_partition_entries();
Does flashing two system partitions increase factory flashing time? No. Pixel didn’t increase in system image size (it merely divided the space across two partitions).