当前位置:   article > 正文

ANDROID 11 文件系统挂载_failed to mount required partitions early

failed to mount required partitions early

源码:http://aospxref.com/ 

系统启动过程可以参看 Android Init 进程启动流程研究

第一阶段启动  First stage init

init 的main函数:

  1. //system/core/init/main.cpp
  2. using namespace android::init;
  3. int main(int argc, char** argv) {
  4. #if __has_feature(address_sanitizer)
  5. __asan_set_error_report_callback(AsanReportCallback);
  6. #endif
  7. if (!strcmp(basename(argv[0]), "ueventd")) {
  8. return ueventd_main(argc, argv);
  9. }
  10. if (argc > 1) {
  11. if (!strcmp(argv[1], "subcontext")) {
  12. android::base::InitLogging(argv, &android::base::KernelLogger);
  13. const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
  14. return SubcontextMain(argc, argv, &function_map);
  15. }
  16. if (!strcmp(argv[1], "selinux_setup")) {
  17. return SetupSelinux(argv);
  18. }
  19. if (!strcmp(argv[1], "second_stage")) {
  20. return SecondStageMain(argc, argv);
  21. }
  22. }
  23. return FirstStageMain(argc, argv); //--->
  24. }

跟踪 FirstStageMain

  1. ///system/core/init/first_stage_init.cpp
  2. int FirstStageMain(int argc, char** argv) {
  3. if (REBOOT_BOOTLOADER_ON_PANIC) {
  4. InstallRebootSignalHandlers();
  5. }
  6. boot_clock::time_point start_time = boot_clock::now();
  7. std::vector<std::pair<std::string, int>> errors;
  8. #define CHECKCALL(x) \
  9. if ((x) != 0) errors.emplace_back(#x " failed", errno);
  10. // Clear the umask.
  11. umask(0);
  12. CHECKCALL(clearenv());
  13. CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1));
  14. // Get the basic filesystem setup we need put together in the initramdisk
  15. // on / and then we'll let the rc file figure out the rest.
  16. CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"));
  17. CHECKCALL(mkdir("/dev/pts", 0755));
  18. CHECKCALL(mkdir("/dev/socket", 0755));
  19. CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL));
  20. #define MAKE_STR(x) __STRING(x)
  21. CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)));
  22. #undef MAKE_STR
  23. // Don't expose the raw commandline to unprivileged processes.
  24. CHECKCALL(chmod("/proc/cmdline", 0440));
  25. std::string cmdline;
  26. android::base::ReadFileToString("/proc/cmdline", &cmdline);
  27. gid_t groups[] = {AID_READPROC};
  28. CHECKCALL(setgroups(arraysize(groups), groups));
  29. CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL));
  30. CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL));
  31. CHECKCALL(mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11)));
  32. if constexpr (WORLD_WRITABLE_KMSG) {
  33. CHECKCALL(mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11)));
  34. }
  35. CHECKCALL(mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8)));
  36. CHECKCALL(mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9)));
  37. // This is needed for log wrapper, which gets called before ueventd runs.
  38. CHECKCALL(mknod("/dev/ptmx", S_IFCHR | 0666, makedev(5, 2)));
  39. CHECKCALL(mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3)));
  40. // These below mounts are done in first stage init so that first stage mount can mount
  41. // subdirectories of /mnt/{vendor,product}/. Other mounts, not required by first stage mount,
  42. // should be done in rc files.
  43. // Mount staging areas for devices managed by vold
  44. // See storage config details at http://source.android.com/devices/storage/
  45. CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
  46. "mode=0755,uid=0,gid=1000"));
  47. // /mnt/vendor is used to mount vendor-specific partitions that can not be
  48. // part of the vendor partition, e.g. because they are mounted read-write.
  49. CHECKCALL(mkdir("/mnt/vendor", 0755));
  50. // /mnt/product is used to mount product-specific partitions that can not be
  51. // part of the product partition, e.g. because they are mounted read-write.
  52. CHECKCALL(mkdir("/mnt/product", 0755));
  53. // /debug_ramdisk is used to preserve additional files from the debug ramdisk
  54. CHECKCALL(mount("tmpfs", "/debug_ramdisk", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
  55. "mode=0755,uid=0,gid=0"));
  56. #undef CHECKCALL
  57. SetStdioToDevNull(argv);
  58. // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
  59. // talk to the outside world...
  60. InitKernelLogging(argv);
  61. if (!errors.empty()) {
  62. for (const auto& [error_string, error_errno] : errors) {
  63. LOG(ERROR) << error_string << " " << strerror(error_errno);
  64. }
  65. LOG(FATAL) << "Init encountered errors starting first stage, aborting";
  66. }
  67. LOG(INFO) << "init first stage started!";
  68. auto old_root_dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/"), closedir};
  69. if (!old_root_dir) {
  70. PLOG(ERROR) << "Could not opendir(\"/\"), not freeing ramdisk";
  71. }
  72. struct stat old_root_info;
  73. if (stat("/", &old_root_info) != 0) {
  74. PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk";
  75. old_root_dir.reset();
  76. }
  77. auto want_console = ALLOW_FIRST_STAGE_CONSOLE ? FirstStageConsole(cmdline) : 0;
  78. if (!LoadKernelModules(IsRecoveryMode() && !ForceNormalBoot(cmdline), want_console)) {
  79. if (want_console != FirstStageConsoleParam::DISABLED) {
  80. LOG(ERROR) << "Failed to load kernel modules, starting console";
  81. } else {
  82. LOG(FATAL) << "Failed to load kernel modules";
  83. }
  84. }
  85. if (want_console == FirstStageConsoleParam::CONSOLE_ON_FAILURE) {
  86. StartConsole();
  87. }
  88. if (ForceNormalBoot(cmdline)) {
  89. mkdir("/first_stage_ramdisk", 0755);
  90. // SwitchRoot() must be called with a mount point as the target, so we bind mount the
  91. // target directory to itself here.
  92. if (mount("/first_stage_ramdisk", "/first_stage_ramdisk", nullptr, MS_BIND, nullptr) != 0) {
  93. LOG(FATAL) << "Could not bind mount /first_stage_ramdisk to itself";
  94. }
  95. SwitchRoot("/first_stage_ramdisk");
  96. }
  97. // If this file is present, the second-stage init will use a userdebug sepolicy
  98. // and load adb_debug.prop to allow adb root, if the device is unlocked.
  99. if (access("/force_debuggable", F_OK) == 0) {
  100. std::error_code ec; // to invoke the overloaded copy_file() that won't throw.
  101. if (!fs::copy_file("/adb_debug.prop", kDebugRamdiskProp, ec) ||
  102. !fs::copy_file("/userdebug_plat_sepolicy.cil", kDebugRamdiskSEPolicy, ec)) {
  103. LOG(ERROR) << "Failed to setup debug ramdisk";
  104. } else {
  105. // setenv for second-stage init to read above kDebugRamdisk* files.
  106. setenv("INIT_FORCE_DEBUGGABLE", "true", 1);
  107. }
  108. }
  109. if (!DoFirstStageMount()) { //--->
  110. LOG(FATAL) << "Failed to mount required partitions early ...";
  111. }
  112. struct stat new_root_info;
  113. if (stat("/", &new_root_info) != 0) {
  114. PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk";
  115. old_root_dir.reset();
  116. }
  117. if (old_root_dir && old_root_info.st_dev != new_root_info.st_dev) {
  118. FreeRamdisk(old_root_dir.get(), old_root_info.st_dev);
  119. }
  120. SetInitAvbVersionInRecovery();
  121. setenv(kEnvFirstStageStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(),
  122. 1);
  123. const char* path = "/system/bin/init";
  124. const char* args[] = {path, "selinux_setup", nullptr};
  125. auto fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC);
  126. dup2(fd, STDOUT_FILENO);
  127. dup2(fd, STDERR_FILENO);
  128. close(fd);
  129. execv(path, const_cast<char**>(args));
  130. // execv() only returns if an error happened, in which case we
  131. // panic and never fall through this conditional.
  132. PLOG(FATAL) << "execv(\"" << path << "\") failed";
  133. return 1;
  134. }

DoFirstStageMount

  1. //system/core/init/first_stage_mount.cpp
  2. // Public functions
  3. // ----------------
  4. // Mounts partitions specified by fstab in device tree.
  5. bool DoFirstStageMount() {
  6. // Skips first stage mount if we're in recovery mode.
  7. if (IsRecoveryMode()) {
  8. LOG(INFO) << "First stage mount skipped (recovery mode)";
  9. return true;
  10. }
  11. std::unique_ptr<FirstStageMount> handle = FirstStageMount::Create();
  12. if (!handle) {
  13. LOG(ERROR) << "Failed to create FirstStageMount";
  14. return false;
  15. }
  16. return handle->DoFirstStageMount();
  17. }
  18. std::unique_ptr<FirstStageMount> FirstStageMount::Create() {
  19. auto fstab = ReadFirstStageFstab();
  20. if (IsDtVbmetaCompatible(fstab)) {
  21. return std::make_unique<FirstStageMountVBootV2>(std::move(fstab));
  22. } else {
  23. return std::make_unique<FirstStageMountVBootV1>(std::move(fstab));
  24. }
  25. }
  26. static Fstab ReadFirstStageFstab() {
  27. Fstab fstab;
  28. //bool ReadFstabFromDt(Fstab* fstab, bool log = true);
  29. if (!ReadFstabFromDt(&fstab)) { //???
  30. if (ReadDefaultFstab(&fstab)) { //???
  31. fstab.erase(std::remove_if(fstab.begin(), fstab.end(),
  32. [](const auto& entry) {
  33. return !entry.fs_mgr_flags.first_stage_mount;
  34. }),
  35. fstab.end());
  36. } else {
  37. LOG(INFO) << "Failed to fstab for first stage mount";
  38. }
  39. }
  40. return fstab;
  41. }
  42. bool FirstStageMount::DoFirstStageMount() {
  43. if (!IsDmLinearEnabled() && fstab_.empty()) {
  44. // Nothing to mount.
  45. LOG(INFO) << "First stage mount skipped (missing/incompatible/empty fstab in device tree)";
  46. return true;
  47. }
  48. if (!InitDevices()) return false;
  49. if (!MountPartitions()) return false;
  50. return true;
  51. }
  52. bool FirstStageMount::InitDevices() {
  53. std::set<std::string> devices;
  54. GetSuperDeviceName(&devices);
  55. if (!GetDmVerityDevices(&devices)) {
  56. return false;
  57. }
  58. if (!InitRequiredDevices(std::move(devices))) {
  59. return false;
  60. }
  61. if (IsDmLinearEnabled()) {
  62. auto super_symlink = "/dev/block/by-name/"s + super_partition_name_;
  63. if (!android::base::Realpath(super_symlink, &super_path_)) {
  64. PLOG(ERROR) << "realpath failed: " << super_symlink;
  65. return false;
  66. }
  67. }
  68. return true;
  69. }
  70. void FirstStageMount::GetSuperDeviceName(std::set<std::string>* devices) {
  71. // Add any additional devices required for dm-linear mappings.
  72. if (!IsDmLinearEnabled()) {
  73. return;
  74. }
  75. devices->emplace(super_partition_name_);
  76. }
  77. FirstStageMount::FirstStageMount(Fstab fstab) : need_dm_verity_(false), fstab_(std::move(fstab)) {
  78. super_partition_name_ = fs_mgr_get_super_partition_name(); //???
  79. }
  80. // Creates devices with uevent->partition_name matching ones in the given set.
  81. // Found partitions will then be removed from it for the subsequent member
  82. // function to check which devices are NOT created.
  83. bool FirstStageMount::InitRequiredDevices(std::set<std::string> devices) {
  84. //BlockDevInitializer block_dev_init_;
  85. //往/sys目录下的所有设备发送uevent事件,创建device-mapper设备节点
  86. if (!block_dev_init_.InitDeviceMapper()) { //???
  87. return false;
  88. }
  89. if (devices.empty()) {
  90. return true;
  91. }
  92. //创建dts中的vbmeta,vbmeta_system,vbmeta_vendor,boot,super分区设备
  93. return block_dev_init_.InitDevices(std::move(devices)); //???
  94. }

由于对GetSuperDeviceName不太明白,搜到如下文章 android R启动找不到super分区问题

  1. //system/core/fs_mgr/fs_mgr_fstab.cpp
  2. // Returns fstab entries parsed from the device tree if they exist
  3. bool ReadFstabFromDt(Fstab* fstab, bool log) {
  4. std::string fstab_buf = ReadFstabFromDt();
  5. if (fstab_buf.empty()) {
  6. if (log) LINFO << __FUNCTION__ << "(): failed to read fstab from dt";
  7. return false;
  8. }
  9. std::unique_ptr<FILE, decltype(&fclose)> fstab_file(
  10. fmemopen(static_cast<void*>(const_cast<char*>(fstab_buf.c_str())),
  11. fstab_buf.length(), "r"), fclose);
  12. if (!fstab_file) {
  13. if (log) PERROR << __FUNCTION__ << "(): failed to create a file stream for fstab dt";
  14. return false;
  15. }
  16. if (!ReadFstabFile(fstab_file.get(), false, fstab)) {
  17. if (log) {
  18. LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:" << std::endl
  19. << fstab_buf;
  20. }
  21. return false;
  22. }
  23. #ifndef NO_SKIP_MOUNT
  24. SkipMountingPartitions(fstab);
  25. #endif
  26. return true;
  27. }
  28. std::string ReadFstabFromDt() {
  29. if (!is_dt_compatible() || !IsDtFstabCompatible()) {
  30. return {};
  31. }
  32. //const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android/");
  33. //get_android_dt_dir 获取kernel命令行 "androidboot.android_dt_dir" 的键值,没有的话用kDefaultAndroidDtDir
  34. //kernel cmdline ----> cat /proc/cmdline
  35. std::string fstabdir_name = get_android_dt_dir() + "/fstab";
  36. std::unique_ptr<DIR, int (*)(DIR*)> fstabdir(opendir(fstabdir_name.c_str()), closedir);
  37. if (!fstabdir) return {}; //553没有dt fstab 直接返回
  38. dirent* dp;
  39. // Each element in fstab_dt_entries is <mount point, the line format in fstab file>.
  40. std::vector<std::pair<std::string, std::string>> fstab_dt_entries;
  41. while ((dp = readdir(fstabdir.get())) != NULL) {
  42. // skip over name, compatible and .
  43. if (dp->d_type != DT_DIR || dp->d_name[0] == '.') continue;
  44. // create <dev> <mnt_point> <type> <mnt_flags> <fsmgr_flags>\n
  45. std::vector<std::string> fstab_entry;
  46. std::string file_name;
  47. std::string value;
  48. // skip a partition entry if the status property is present and not set to ok
  49. file_name = android::base::StringPrintf("%s/%s/status", fstabdir_name.c_str(), dp->d_name);
  50. if (ReadDtFile(file_name, &value)) {
  51. if (value != "okay" && value != "ok") {
  52. LINFO << "dt_fstab: Skip disabled entry for partition " << dp->d_name;
  53. continue;
  54. }
  55. }
  56. file_name = android::base::StringPrintf("%s/%s/dev", fstabdir_name.c_str(), dp->d_name);
  57. if (!ReadDtFile(file_name, &value)) {
  58. LERROR << "dt_fstab: Failed to find device for partition " << dp->d_name;
  59. return {};
  60. }
  61. fstab_entry.push_back(value);
  62. std::string mount_point;
  63. file_name =
  64. android::base::StringPrintf("%s/%s/mnt_point", fstabdir_name.c_str(), dp->d_name);
  65. if (ReadDtFile(file_name, &value)) {
  66. LINFO << "dt_fstab: Using a specified mount point " << value << " for " << dp->d_name;
  67. mount_point = value;
  68. } else {
  69. mount_point = android::base::StringPrintf("/%s", dp->d_name);
  70. }
  71. fstab_entry.push_back(mount_point);
  72. file_name = android::base::StringPrintf("%s/%s/type", fstabdir_name.c_str(), dp->d_name);
  73. if (!ReadDtFile(file_name, &value)) {
  74. LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
  75. return {};
  76. }
  77. fstab_entry.push_back(value);
  78. file_name = android::base::StringPrintf("%s/%s/mnt_flags", fstabdir_name.c_str(), dp->d_name);
  79. if (!ReadDtFile(file_name, &value)) {
  80. LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
  81. return {};
  82. }
  83. fstab_entry.push_back(value);
  84. file_name = android::base::StringPrintf("%s/%s/fsmgr_flags", fstabdir_name.c_str(), dp->d_name);
  85. if (!ReadDtFile(file_name, &value)) {
  86. LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
  87. return {};
  88. }
  89. fstab_entry.push_back(value);
  90. // Adds a fstab_entry to fstab_dt_entries, to be sorted by mount_point later.
  91. fstab_dt_entries.emplace_back(mount_point, android::base::Join(fstab_entry, " "));
  92. }
  93. // Sort fstab_dt entries, to ensure /vendor is mounted before /vendor/abc is attempted.
  94. std::sort(fstab_dt_entries.begin(), fstab_dt_entries.end(),
  95. [](const auto& a, const auto& b) { return a.first < b.first; });
  96. std::string fstab_result;
  97. for (const auto& [_, dt_entry] : fstab_dt_entries) {
  98. fstab_result += dt_entry + "\n";
  99. }
  100. return fstab_result;
  101. }
  102. // Loads the fstab file and combines with fstab entries passed in from device tree.
  103. bool ReadDefaultFstab(Fstab* fstab) {
  104. Fstab dt_fstab;
  105. ReadFstabFromDt(&dt_fstab, false);
  106. *fstab = std::move(dt_fstab);
  107. std::string default_fstab_path;
  108. // Use different fstab paths for normal boot and recovery boot, respectively
  109. if (access("/system/bin/recovery", F_OK) == 0) { //recovery 模式
  110. default_fstab_path = "/etc/recovery.fstab";
  111. } else { // normal boot
  112. default_fstab_path = GetFstabPath();
  113. }
  114. Fstab default_fstab;
  115. if (!default_fstab_path.empty()) {
  116. ReadFstabFromFile(default_fstab_path, &default_fstab);
  117. } else {
  118. LINFO << __FUNCTION__ << "(): failed to find device default fstab";
  119. }
  120. for (auto&& entry : default_fstab) {
  121. fstab->emplace_back(std::move(entry));
  122. }
  123. return !fstab->empty();
  124. }
  125. // Identify path to fstab file. Lookup is based on pattern
  126. // fstab.<fstab_suffix>, fstab.<hardware>, fstab.<hardware.platform> in
  127. // folders /odm/etc, vendor/etc, or /.
  128. std::string GetFstabPath() {
  129. for (const char* prop : {"fstab_suffix", "hardware", "hardware.platform"}) {
  130. std::string suffix;
  131. //[ro.boot.hardware]: [HNR553T] 只有hardware满足条件
  132. if (!fs_mgr_get_boot_config(prop, &suffix)) continue;
  133. for (const char* prefix : {"/odm/etc/fstab.", "/vendor/etc/fstab.", "/fstab."}) {
  134. std::string fstab_path = prefix + suffix;
  135. if (access(fstab_path.c_str(), F_OK) == 0) {
  136. return fstab_path;
  137. }
  138. }
  139. }
  140. return "";
  141. }

HNR553T:/proc/device-tree/firmware/android # ls
compatible  name  vbmeta

553 的dt没有fstab

HNR553T:/proc/device-tree # find -name "fstab*"
HNR553T:/proc/device-tree # find -name "fstab"
HNR553T:/proc/device-tree # find -name "*fstab"

HNR553T:/ # cat /proc/cmdline
earlycon=sprd_serial,0x20210000,115200n8 console=ttyS1,115200n8 loglevel=1 init=/init root=/dev/ram0 rw printk.devkmsg=on pcie_ports=compat swiotlb=2560 androidboot.hardware=HNR553T androidboot.dtbo_idx=0 lcd_id=ID8756 lcd_name=lcd_ft8756_txd_mipi_hdplus lcd_base=b0000000 lcd_size=2400x1080 logo_bpix=32 androidboot.ddrsize=6144M androidboot.ddrsize.range=[6144,) androidboot.lwfq.type=-1 androidboot.auto.efuse=-1 androidboot.auto.chipid=UMS9620-AA  sysdump_magic=80001000 sysdump_re_flag=1  androidboot.wdten=0  androidboot.dswdten=disable modem=shutdown  androidboot.meid=1  recoverytype=0  androidboot.fuse=0 rfboard.id=1 rfhw.id=18432 crystal=5 32k.less=0 pcb.version=0 androidboot.pmic.chipid=7520 cpcmdline=end powerup_reason=Reboot  androidboot.verifiedbootstate=orange androidboot.flash.locked=0  androidboot.serialno=40322211589811 buildvariant=userdebug androidboot.vbmeta.device=PARTUUID=1.0 androidboot.vbmeta.avb_version=1.1 androidboot.vbmeta.device_state=unlocked androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=42560 androidboot.vbmeta.digest=c6f2d4e0d5d12cf691b2968b844c245f73146227c028bcc91d375531b464f3cb androidboot.vbmeta.invalidate_on_error=yes androidboot.veritymode=enforcing androidboot.slot_suffix=_a androidboot.force_normal_boot=1 androidboot.boot_devices=soc/soc:ap-ahb/22000000.ufs bootcause="Reboot into normal" pwroffcause="device power down" charge.shutdown_rtc_time=-1  charge.charge_cycle=-1  charge.basp=-1  charge.total_mah=-1  androidboot.vendor.skip.init=0

[ro.boot.flash.locked]: [0]
[ro.boot.force_normal_boot]: [1]
[ro.boot.fuse]: [0]
[ro.boot.hardware]: [HNR553T]
[ro.boot.lwfq.type]: [-1]

HNR553T:/ # ls /odm/etc/fstab.*
ls: /odm/etc/fstab.*: No such file or directory

1|HNR553T:/ # ls /vendor/etc/fstab.*
/vendor/etc/fstab.HNR553T      /vendor/etc/fstab.factorytest /vendor/etc/fstab.ums9620_2c11 /vendor/etc/fstab.P50          /vendor/etc/fstab.ums9520_haps        /vendor/etc/fstab.ums9620_2h10 /vendor/etc/fstab.cali         /vendor/etc/fstab.ums9520_haps_flash  /vendor/etc/fstab.ums9620_2h10_car /vendor/etc/fstab.charge_mode  /vendor/etc/fstab.ums9620_1h10        /vendor/etc/fstab.ums9620_3c10 /vendor/etc/fstab.enableswap   /vendor/etc/fstab.ums9620_2c10

HNR553T:/ # ls /fstab.*
ls: /fstab.*: No such file or directory

这样就找到了唯一符合条件的:/vendor/etc/fstab.HNR553T

事实上,经过一星期的琢磨,这个结论是错误的:根据文档提前装载分区,提到“将恢复用作 ramdisk 的设备,第一阶段 init 在装载提前装载分区之前将根操作切换到了 /first_stage_ramdisk,因此设备必须将 fstab 文件放在 $(TARGET_COPY_OUT_RECOVERY)/root/first_stage_ramdisk 中”,通过解包boot.img, 发现first_stage_ramdisk目录下,没有文件夹vendor,但可以可以找到“fstab.HNR553T”,这个文件才是第一阶段要加载的fstab.

│  fstab.HNR553T
│  fstab.P50
│  fstab.ums9520_haps
│  fstab.ums9520_haps_flash
│  fstab.ums9620_1h10
│  fstab.ums9620_2c10
│  fstab.ums9620_2c11
│  fstab.ums9620_2h10
│  fstab.ums9620_2h10_car
│  fstab.ums9620_2h10_uob
│  fstab.ums9620_3c10

├─avb
│      q-gsi.avbpubkey
│      r-gsi.avbpubkey
│      s-gsi.avbpubkey

└─system
    └─bin
            e2fsck

/fstab.HNR553T 

#Dynamic partitions fstab file
#<dev> <mnt_point> <type> <mnt_flags options>  <fs_mgr_flags>

system /system ext4 ro,barrier=1 wait,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey,slotselect
vendor /vendor ext4 ro,barrier=1 wait,avb=vbmeta_vendor,logical,first_stage_mount,slotselect
system_ext /system_ext ext4 ro,barrier=1 wait,avb=vbmeta_system_ext,logical,first_stage_mount,slotselect
product /product ext4 ro,barrier=1 wait,avb=vbmeta_product,logical,first_stage_mount,slotselect
/dev/block/by-name/metadata /metadata    ext4 nodev,noatime,nosuid,errors=panic wait,formattable,first_stage_mount,check

HNR553T:/ # cat /vendor/etc/fstab.HNR553T
# Android fstab file.
# The filesystem that contains the filesystem checker binary (typically /system) cannot
# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK
# <src>                                         <mnt_point>  <type>  <mnt_flags and options>             <fs_mgr_flags>

system /system ext4 ro,barrier=1 wait,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey,slotselect
system_ext /system_ext ext4 ro,barrier=1 wait,logical,first_stage_mount,slotselect
vendor /vendor ext4 ro,barrier=1 wait,logical,first_stage_mount,slotselect
product /product ext4 ro,barrier=1 wait,logical,first_stage_mount,slotselect
/dev/block/by-name/userdata /data        f2fs noatime,nosuid,nodev,discard,inline_xattr,inline_data,inlinecrypt,fsync_mode=nobarrier latemount,wait,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,check,reservedsize=128M,checkpoint=fs,formattable
/dev/block/by-name/metadata /metadata    ext4 nodev,noatime,nosuid,errors=panic wait,formattable,first_stage_mount,check
/devices/platform/soc/soc:ipa-apb/25100000.usb3/25100000.dwc3/xhci-hcd.*.auto/usb*      auto         vfat defaults voldmanaged=usbdisk:auto
/devices/platform/soc/soc:ap-ahb/22210000.sdio/mmc_host/mmc1/mmc1:*/block/mmcblk1      auto         vfat defaults voldmanaged=sdcard0:auto,noemulatedsd
/dev/block/by-name/prodnv    /mnt/vendor ext4 noatime,nosuid,nodev,nomblk_io_submit,noauto_da_alloc wait,check
/dev/block/by-name/cache    /cache       ext4 noatime,nosuid,nodev,nomblk_io_submit,noauto_da_alloc wait,check
# Should after mount prodnv for prodnv wholly occupying /mnt/vendor
/dev/block/by-name/socko /mnt/vendor/socko ext4 ro,noatime,nosuid,nodev,nomblk_io_submit,noauto_da_alloc wait,avb=socko,slotselect
/dev/block/by-name/odmko /mnt/vendor/odmko ext4 ro,noatime,nosuid,nodev,nomblk_io_submit,noauto_da_alloc wait,avb=odmko,slotselect
/dev/block/by-name/misc     /misc        emmc    defaults    defaults
#/dev/block/memdisk.0    /system      ext4 rw,barrier=1                          wait
#/dev/block/memdisk.1    /data        ext4 noatime,nosuid,nodev,noauto_da_alloc,journal_async_commit,errors=panic wait

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/1005116
推荐阅读
相关标签
  

闽ICP备14008679号