bootctl hal
概述
用于A/B系统切换A/B的hal
源码解析
源码位置:android/hardware/interfaces/boot/1.1/default/boot_control/libboot_control.cpp文件
1. bootctl模块
1.1 IsSlotMarkedSuccessful-正常情况为true,OTA情况为false
bool BootControl::IsSlotMarkedSuccessful(unsigned int slot) {
if (slot >= kMaxNumSlots || slot >= num_slots_) {
// Invalid slot number.
return false;
}
bootloader_control bootctrl; // slot为0
if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
// 当该slot成功启动的时候,该位置1;// 该slot能重启的次数
// 表明此时处于OTA升级阶段或者是第一次刷固件的时候,需要进行checkpoint,这里为false;其他情况为true
return bootctrl.slot_info[slot].successful_boot && bootctrl.slot_info[slot].tries_remaining;
}
1.2 Init-初始化操作
// Initialize the boot_control_private struct with the information from
// the bootloader_message buffer stored in |boot_ctrl|. Returns whether the
// initialization succeeded.
bool BootControl::Init() {
// 只初始化一次
if (initialized_) return true;
// Initialize the current_slot from the read-only property. If the property
// was not set (from either the command line or the device tree), we can later
// initialize it from the bootloader_control struct.
// 这个是内核cmdline上传上来的,uboot设的
std::string suffix_prop = android::base::GetProperty("ro.boot.slot_suffix", "");
if (suffix_prop.empty()) {
LOG(ERROR) << "Slot suffix property is not set";
return false;
}// _a为0
current_slot_ = SlotSuffixToIndex(suffix_prop.c_str());
std::string err;// fstab文件中配置的/misc,/dev/block/by-name/misc
std::string device = get_bootloader_message_blk_device(&err);
if (device.empty()) {
LOG(ERROR) << "Could not find bootloader message block device: " << err;
return false;
}
bootloader_control boot_ctrl;
// 读misc分区
if (!LoadBootloaderControl(device.c_str(), &boot_ctrl)) {
LOG(ERROR) << "Failed to load bootloader control block";
return false;
}
// Note that since there isn't a module unload function this memory is leaked.
// We use `device` below sometimes, so it's not moved out of here.
misc_device_ = device;
initialized_ = true;
// Validate the loaded data, otherwise we will destroy it and re-initialize it
// with the current information.
// crc32错误检测
uint32_t computed_crc32 = BootloaderControlLECRC(&boot_ctrl);
// 我们事先生成了一个misc.img,里面都是计算好的,所以是一致的
if (boot_ctrl.crc32_le != computed_crc32) {
LOG(WARNING) << "Invalid boot control found, expected CRC-32 0x" << std::hex << computed_crc32
<< " but found 0x" << std::hex << boot_ctrl.crc32_le << ". Re-initializing.";
InitDefaultBootloaderControl(this, &boot_ctrl);
UpdateAndSaveBootloaderControl(device.c_str(), &boot_ctrl);
}
// 事先生成的misc.img,不需要生成
if (!InitMiscVirtualAbMessageIfNeeded()) {
return false;
}
num_slots_ = boot_ctrl.nb_slot; // 这个为2
return true;
}
1.3 SlotSuffixToIndex
constexpr unsigned int kMaxNumSlots =
sizeof(bootloader_control::slot_info) / sizeof(bootloader_control::slot_info[0]); // 为4个
constexpr const char* kSlotSuffixes[kMaxNumSlots] = { "_a", "_b", "_c", "_d" };
int SlotSuffixToIndex(const char* suffix) {
for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
if (!strcmp(kSlotSuffixes[slot], suffix)) return slot; // _a为0
}
return -1;
}
1.4 LoadBootloaderControl-读misc分区中的bootloader_message_ab数据结构
bool LoadBootloaderControl(const std::string& misc_device, bootloader_control* buffer) {
android::base::unique_fd fd(open(misc_device.c_str(), O_RDONLY));
if (fd.get() == -1) {
PLOG(ERROR) << "failed to open " << misc_device;
return false;
}// constexpr off_t kBootloaderControlOffset = offsetof(bootloader_message_ab, slot_suffix);
// 读bootloader_control信息
if (lseek(fd, kBootloaderControlOffset, SEEK_SET) != kBootloaderControlOffset) {
PLOG(ERROR) << "failed to lseek " << misc_device;
return false;
}
if (!android::base::ReadFully(fd.get(), buffer, sizeof(bootloader_control))) {
PLOG(ERROR) << "failed to read " << misc_device;
return false;
}
return true;
}
1.5 get_bootloader_message_blk_device-返回fsatb中配置的misc分区的路径
android/bootable/recovery/bootloader_message/bootloader_message.cpp文件
std::string get_bootloader_message_blk_device(std::string* err) {
std::string misc_blk_device = get_misc_blk_device(err);
if (misc_blk_device.empty()) return "";
if (!wait_for_device(misc_blk_device, err)) return "";
return misc_blk_device;
}
std::string get_misc_blk_device(std::string* err) {
if (g_misc_device_for_test.has_value() && !g_misc_device_for_test->empty()) {
return *g_misc_device_for_test;
}
Fstab fstab;
if (!ReadDefaultFstab(&fstab)) {
*err = "failed to read default fstab";
return "";
}
for (const auto& entry : fstab) {
// fstab中配置的
if (entry.mount_point == "/misc") {
return entry.blk_device;
}
}
*err = "failed to find /misc partition";
return "";
}
1.6 BootloaderControlLECRC-计算CRC32
static uint32_t CRC32(const uint8_t* buf, size_t size) {
static uint32_t crc_table[256]; // static类型的,只生成一次crc_table
// Compute the CRC-32 table only once.
if (!crc_table[1]) {
for (uint32_t i = 0; i < 256; ++i) {
uint32_t crc = i;
for (uint32_t j = 0; j < 8; ++j) {
uint32_t mask = -(crc & 1);
crc = (crc >> 1) ^ (0xEDB88320 & mask);
}
crc_table[i] = crc;
}
}
uint32_t ret = -1;
for (size_t i = 0; i < size; ++i) {
ret = (ret >> 8) ^ crc_table[(ret ^ buf[i]) & 0xFF]; // 计算CRC32
}
return ~ret;
}
// Return the little-endian representation of the CRC-32 of the first fields
// in |boot_ctrl| up to the crc32_le field.
uint32_t BootloaderControlLECRC(const bootloader_control* boot_ctrl) {
return htole32(
CRC32(reinterpret_cast<const uint8_t*>(boot_ctrl), offsetof(bootloader_control, crc32_le)));
}
bool InitMiscVirtualAbMessageIfNeeded() {
std::string err;
misc_virtual_ab_message message;
// 读misc分区
if (!ReadMiscVirtualAbMessage(&message, &err)) {
LOG(ERROR) << "Could not read merge status: " << err;
return false;
}
// 这里直接返回
if (message.version == MISC_VIRTUAL_AB_MESSAGE_VERSION &&
message.magic == MISC_VIRTUAL_AB_MAGIC_HEADER) {
// Already initialized.
return true;
}
message = {};
message.version = MISC_VIRTUAL_AB_MESSAGE_VERSION;
message.magic = MISC_VIRTUAL_AB_MAGIC_HEADER;
if (!WriteMiscVirtualAbMessage(message, &err)) {
LOG(ERROR) << "Could not write merge status: " << err;
return false;
}
return true;
}
1.7 GetCurrentSlot
unsigned int BootControl::GetCurrentSlot() {
return current_slot_; // 默认为0
}
2. Misc分区中相关的数据结构
源码位置:android/hardware/interfaces/boot/1.1/default/boot_control/include/private/boot_control_definition.h文件
2.1 bootloader_message_ab数据结构
struct bootloader_message_ab {
struct bootloader_message message; // 2048字节
char slot_suffix[32]; // 为bootloader_control数据结构,相关的信息都存放于此
char update_channel[128];
char reserved[1888];
};
2.2 bootloader_control 数据结构
struct bootloader_control {
// NUL terminated active slot suffix.
char slot_suffix[4]; // 存放_a或者_b
// Bootloader Control AB magic number (see BOOT_CTRL_MAGIC).
uint32_t magic; // 为0x42414342
// Version of struct being used (see BOOT_CTRL_VERSION).
uint8_t version; // 为1
// Number of slots being managed.
uint8_t nb_slot : 3; // slot的数目,一般为2(AB)
// Number of times left attempting to boot recovery.
uint8_t recovery_tries_remaining : 3;
// Status of any pending snapshot merge of dynamic partitions.
uint8_t merge_status : 3;
// Ensure 4-bytes alignment for slot_info field.
uint8_t reserved0[1];
// Per-slot information. Up to 4 slots.
struct slot_metadata slot_info[4]; // 最大支持4个slot
// Reserved for further use.
uint8_t reserved1[8];
// CRC32 of all 28 bytes preceding this field (little endian
// format).
uint32_t crc32_le;
} __attribute__((packed));
2.3 slot_metadata数据结构
struct slot_metadata {
// Slot priority with 15 meaning highest priority, 1 lowest
// priority and 0 the slot is unbootable.
uint8_t priority : 4; // slot的优先级,优先级高的先启动,最高为15,最低为1。为0时不给启动
// Number of times left attempting to boot this slot.
uint8_t tries_remaining : 3; // 该slot能重启的次数
// 1 if this slot has booted successfully, 0 otherwise.
uint8_t successful_boot : 1; // 当该slot成功启动的时候,该位置1
// 1 if this slot is corrupted from a dm-verity corruption, 0
// otherwise.
uint8_t verity_corrupted : 1; // 目前无人设此值1
// Reserved for further use.
uint8_t reserved : 7;
} __attribute__((packed));
2.4 misc分区数据
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| // bootloader_message数据结构
*
00000800 61 00 00 00 42 43 41 42 01 02 00 00 9f 00 7f 00 |a...BCAB........| // slot_suffix bootloader_control
00000810 00 00 00 00 00 00 00 00 00 00 00 00 7c fd 96 02 |............|...|
00000820 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00008000 02 b0 0a 74 56 00 00 00 00 00 00 00 00 00 00 00 |...tV...........|
00008010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
01000000