如刚才实验,烧录GSI之后,本来已经被格式化为ext4的metadata分区,又被格式化为无格式的分区。
我这边继续Check发现,在替换GSI的SOP中,fastboot –w选项如果在bootloader执行,会清userdata、cache、metadata分区为无格式分区,而后进入recovery再次格式化成ext4。
FLOW如下:
a. fastboot程序-w选项如果在loader中执行会传命令给loader清userdata,cache,metadata分区
https://android.googlesource.com/platform/system/core/+/refs/heads/master/fastboot/fastboot.cpp
if (wants_wipe) { if (force_flash) { CancelSnapshotIfNeeded(); } std::vector<std::string> partitions = { "userdata", "cache", "metadata" }; for (const auto& partition : partitions) { std::string partition_type; if (fb->GetVar("partition-type:" + partition, &partition_type) != fastboot::SUCCESS) { continue; } if (partition_type.empty()) continue; fb->Erase(partition); if (partition == "userdata" && set_fbe_marker) { fprintf(stderr, "setting FBE marker on initial userdata...\n"); std::string initial_userdata_dir = create_fbemarker_tmpdir(); fb_perform_format(partition, 1, partition_type, "", initial_userdata_dir, fs_options); delete_fbemarker_tmpdir(initial_userdata_dir); } else { fb_perform_format(partition, 1, partition_type, "", "", fs_options); } } }
b. bootloader根据fastboot传下的分区列表清除对应分区。
c. recovery收到wipe=data会格式化userdata,cache,metadata分区为ext4格式.
https://android.googlesource.com/platform/bootable/recovery/+/refs/heads/master/recovery.cpp
case Device::WIPE_DATA: save_current_log = true; if (ui->IsTextVisible()) { if (ask_to_wipe_data(device)) { WipeData(device, false); } } else { WipeData(device, false); return Device::NO_ACTION; } break;
但是目前的情况是做完fastboot –w选项之后,发现userdata,cache都被格式化为ext4格式,而metadata分区未被格式化,所以猜想recovery没有格式化metadata,
进一步看code可以看到,recovery中如果要格式化metadata,需要volume_for_mount_point返回非空指针,
https://android.googlesource.com/platform/bootable/recovery/+/refs/heads/master/install/wipe_data.cpp
bool WipeData(Device* device, bool convert_fbe) { RecoveryUI* ui = device->GetUI(); ui->Print("\n-- Wiping data...\n"); if (!FinishPendingSnapshotMerges(device)) { ui->Print("Unable to check update status or complete merge, cannot wipe partitions.\n"); return false; } bool success = device->PreWipeData(); if (success) { success &= EraseVolume(DATA_ROOT, ui, convert_fbe); bool has_cache = volume_for_mount_point("/cache") != nullptr; if (has_cache) { success &= EraseVolume(CACHE_ROOT, ui, false); } if (volume_for_mount_point(METADATA_ROOT) != nullptr) { success &= EraseVolume(METADATA_ROOT, ui, false); } } if (success) { success &= device->PostWipeData(); } ui->Print("Data wipe %s.\n", success ? "complete" : "failed"); return success; }
而volume_for_mount_point调用GetEntryForMountPoint,根据entry.mount_point判断METADATA是否存在,如果存在就返回METADATA的挂载路径,
然后EraseVolume函数会umount设备,再调用wipe_block_device清数据以及调用/system/bin/mke2fs格式化。
https://android.googlesource.com/platform/bootable/recovery/+/refs/heads/master/install/wipe_data.cpp
static bool EraseVolume(const char* volume, RecoveryUI* ui, bool convert_fbe) { bool is_cache = (strcmp(volume, CACHE_ROOT) == 0); bool is_data = (strcmp(volume, DATA_ROOT) == 0); ui->SetBackground(RecoveryUI::ERASING); ui->SetProgressType(RecoveryUI::INDETERMINATE); std::vector<saved_log_file> log_files; if (is_cache) { // If we're reformatting /cache, we load any past logs (i.e. "/cache/recovery/last_*") and the // current log ("/cache/recovery/log") into memory, so we can restore them after the reformat. log_files = ReadLogFilesToMemory(); } ui->Print("Formatting %s...\n", volume); ensure_path_unmounted(volume); int result; if (is_data && convert_fbe) { constexpr const char* CONVERT_FBE_DIR = "/tmp/convert_fbe"; constexpr const char* CONVERT_FBE_FILE = "/tmp/convert_fbe/convert_fbe"; // Create convert_fbe breadcrumb file to signal init to convert to file based encryption, not // full disk encryption. if (mkdir(CONVERT_FBE_DIR, 0700) != 0) { PLOG(ERROR) << "Failed to mkdir " << CONVERT_FBE_DIR; return false; } FILE* f = fopen(CONVERT_FBE_FILE, "wbe"); if (!f) { PLOG(ERROR) << "Failed to convert to file encryption"; return false; } fclose(f); result = format_volume(volume, CONVERT_FBE_DIR); remove(CONVERT_FBE_FILE); rmdir(CONVERT_FBE_DIR); } else { result = format_volume(volume); } if (is_cache) { RestoreLogFilesAfterFormat(log_files); } return (result == 0); }
因为目前看到metadata未被格式化,因此有可能类entry中没有metadata分区相关信息,所以继续查找entry的fstab如何获取的,
在fs_mgr_fstab.cpp中可以看到if(access(/system/bin/recovery, F_OK))表示当前是recovery启动,则读取recovery.fstab作为default_fstab_path。
https://android.googlesource.com/platform/system/core/+/refs/heads/master/fs_mgr/fs_mgr_fstab.cpp
// Loads the fstab file and combines with fstab entries passed in from device tree. bool ReadDefaultFstab(Fstab* fstab) { Fstab dt_fstab; ReadFstabFromDt(&dt_fstab, false); *fstab = std::move(dt_fstab); std::string default_fstab_path; // Use different fstab paths for normal boot and recovery boot, respectively if (access("/system/bin/recovery", F_OK) == 0) { default_fstab_path = "/etc/recovery.fstab"; } else { // normal boot default_fstab_path = GetFstabPath(); } Fstab default_fstab; if (!default_fstab_path.empty()) { ReadFstabFromFile(default_fstab_path, &default_fstab); } else { LINFO << __FUNCTION__ << "(): failed to find device default fstab"; } for (auto&& entry : default_fstab) { fstab->emplace_back(std::move(entry)); } return !fstab->empty(); }
如果需要Check一下recovery.fstab中的内容,因为recovery.fstab是从在AN目录下打包过去的,所以在device下看到recovery有3张fstab,检查发现,3张表都是没有metadata分区的。
所以要看一下这里加上metadata后是否可以。