赞
踩
系统启动过程可以参看 Android Init 进程启动流程研究
第一阶段启动 First stage init
init 的main函数:
- //system/core/init/main.cpp
- using namespace android::init;
-
- int main(int argc, char** argv) {
- #if __has_feature(address_sanitizer)
- __asan_set_error_report_callback(AsanReportCallback);
- #endif
-
- if (!strcmp(basename(argv[0]), "ueventd")) {
- return ueventd_main(argc, argv);
- }
-
- if (argc > 1) {
- if (!strcmp(argv[1], "subcontext")) {
- android::base::InitLogging(argv, &android::base::KernelLogger);
- const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
-
- return SubcontextMain(argc, argv, &function_map);
- }
-
- if (!strcmp(argv[1], "selinux_setup")) {
- return SetupSelinux(argv);
- }
-
- if (!strcmp(argv[1], "second_stage")) {
- return SecondStageMain(argc, argv);
- }
- }
-
- return FirstStageMain(argc, argv); //--->
- }
跟踪 FirstStageMain
- ///system/core/init/first_stage_init.cpp
- int FirstStageMain(int argc, char** argv) {
- if (REBOOT_BOOTLOADER_ON_PANIC) {
- InstallRebootSignalHandlers();
- }
-
- boot_clock::time_point start_time = boot_clock::now();
-
- std::vector<std::pair<std::string, int>> errors;
- #define CHECKCALL(x) \
- if ((x) != 0) errors.emplace_back(#x " failed", errno);
-
- // Clear the umask.
- umask(0);
-
- CHECKCALL(clearenv());
- CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1));
- // Get the basic filesystem setup we need put together in the initramdisk
- // on / and then we'll let the rc file figure out the rest.
- CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"));
- CHECKCALL(mkdir("/dev/pts", 0755));
- CHECKCALL(mkdir("/dev/socket", 0755));
- CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL));
- #define MAKE_STR(x) __STRING(x)
- CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)));
- #undef MAKE_STR
- // Don't expose the raw commandline to unprivileged processes.
- CHECKCALL(chmod("/proc/cmdline", 0440));
- std::string cmdline;
- android::base::ReadFileToString("/proc/cmdline", &cmdline);
- gid_t groups[] = {AID_READPROC};
- CHECKCALL(setgroups(arraysize(groups), groups));
- CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL));
- CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL));
-
- CHECKCALL(mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11)));
-
- if constexpr (WORLD_WRITABLE_KMSG) {
- CHECKCALL(mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11)));
- }
-
- CHECKCALL(mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8)));
- CHECKCALL(mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9)));
-
- // This is needed for log wrapper, which gets called before ueventd runs.
- CHECKCALL(mknod("/dev/ptmx", S_IFCHR | 0666, makedev(5, 2)));
- CHECKCALL(mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3)));
-
- // These below mounts are done in first stage init so that first stage mount can mount
- // subdirectories of /mnt/{vendor,product}/. Other mounts, not required by first stage mount,
- // should be done in rc files.
- // Mount staging areas for devices managed by vold
- // See storage config details at http://source.android.com/devices/storage/
- CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
- "mode=0755,uid=0,gid=1000"));
- // /mnt/vendor is used to mount vendor-specific partitions that can not be
- // part of the vendor partition, e.g. because they are mounted read-write.
- CHECKCALL(mkdir("/mnt/vendor", 0755));
- // /mnt/product is used to mount product-specific partitions that can not be
- // part of the product partition, e.g. because they are mounted read-write.
- CHECKCALL(mkdir("/mnt/product", 0755));
-
- // /debug_ramdisk is used to preserve additional files from the debug ramdisk
- CHECKCALL(mount("tmpfs", "/debug_ramdisk", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
- "mode=0755,uid=0,gid=0"));
- #undef CHECKCALL
-
- SetStdioToDevNull(argv);
- // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
- // talk to the outside world...
- InitKernelLogging(argv);
-
- if (!errors.empty()) {
- for (const auto& [error_string, error_errno] : errors) {
- LOG(ERROR) << error_string << " " << strerror(error_errno);
- }
- LOG(FATAL) << "Init encountered errors starting first stage, aborting";
- }
-
- LOG(INFO) << "init first stage started!";
-
- auto old_root_dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/"), closedir};
- if (!old_root_dir) {
- PLOG(ERROR) << "Could not opendir(\"/\"), not freeing ramdisk";
- }
-
- struct stat old_root_info;
- if (stat("/", &old_root_info) != 0) {
- PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk";
- old_root_dir.reset();
- }
-
- auto want_console = ALLOW_FIRST_STAGE_CONSOLE ? FirstStageConsole(cmdline) : 0;
-
- if (!LoadKernelModules(IsRecoveryMode() && !ForceNormalBoot(cmdline), want_console)) {
- if (want_console != FirstStageConsoleParam::DISABLED) {
- LOG(ERROR) << "Failed to load kernel modules, starting console";
- } else {
- LOG(FATAL) << "Failed to load kernel modules";
- }
- }
-
- if (want_console == FirstStageConsoleParam::CONSOLE_ON_FAILURE) {
- StartConsole();
- }
-
- if (ForceNormalBoot(cmdline)) {
- mkdir("/first_stage_ramdisk", 0755);
- // SwitchRoot() must be called with a mount point as the target, so we bind mount the
- // target directory to itself here.
- if (mount("/first_stage_ramdisk", "/first_stage_ramdisk", nullptr, MS_BIND, nullptr) != 0) {
- LOG(FATAL) << "Could not bind mount /first_stage_ramdisk to itself";
- }
- SwitchRoot("/first_stage_ramdisk");
- }
-
- // If this file is present, the second-stage init will use a userdebug sepolicy
- // and load adb_debug.prop to allow adb root, if the device is unlocked.
- if (access("/force_debuggable", F_OK) == 0) {
- std::error_code ec; // to invoke the overloaded copy_file() that won't throw.
- if (!fs::copy_file("/adb_debug.prop", kDebugRamdiskProp, ec) ||
- !fs::copy_file("/userdebug_plat_sepolicy.cil", kDebugRamdiskSEPolicy, ec)) {
- LOG(ERROR) << "Failed to setup debug ramdisk";
- } else {
- // setenv for second-stage init to read above kDebugRamdisk* files.
- setenv("INIT_FORCE_DEBUGGABLE", "true", 1);
- }
- }
-
- if (!DoFirstStageMount()) { //--->
- LOG(FATAL) << "Failed to mount required partitions early ...";
- }
-
- struct stat new_root_info;
- if (stat("/", &new_root_info) != 0) {
- PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk";
- old_root_dir.reset();
- }
-
- if (old_root_dir && old_root_info.st_dev != new_root_info.st_dev) {
- FreeRamdisk(old_root_dir.get(), old_root_info.st_dev);
- }
-
- SetInitAvbVersionInRecovery();
-
- setenv(kEnvFirstStageStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(),
- 1);
-
- const char* path = "/system/bin/init";
- const char* args[] = {path, "selinux_setup", nullptr};
- auto fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC);
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
- close(fd);
- execv(path, const_cast<char**>(args));
-
- // execv() only returns if an error happened, in which case we
- // panic and never fall through this conditional.
- PLOG(FATAL) << "execv(\"" << path << "\") failed";
-
- return 1;
- }
DoFirstStageMount
- //system/core/init/first_stage_mount.cpp
- // Public functions
- // ----------------
- // Mounts partitions specified by fstab in device tree.
- bool DoFirstStageMount() {
- // Skips first stage mount if we're in recovery mode.
- if (IsRecoveryMode()) {
- LOG(INFO) << "First stage mount skipped (recovery mode)";
- return true;
- }
-
- std::unique_ptr<FirstStageMount> handle = FirstStageMount::Create();
- if (!handle) {
- LOG(ERROR) << "Failed to create FirstStageMount";
- return false;
- }
- return handle->DoFirstStageMount();
- }
-
- std::unique_ptr<FirstStageMount> FirstStageMount::Create() {
- auto fstab = ReadFirstStageFstab();
- if (IsDtVbmetaCompatible(fstab)) {
- return std::make_unique<FirstStageMountVBootV2>(std::move(fstab));
- } else {
- return std::make_unique<FirstStageMountVBootV1>(std::move(fstab));
- }
- }
-
- static Fstab ReadFirstStageFstab() {
- Fstab fstab;
- //bool ReadFstabFromDt(Fstab* fstab, bool log = true);
- if (!ReadFstabFromDt(&fstab)) { //???
- if (ReadDefaultFstab(&fstab)) { //???
- fstab.erase(std::remove_if(fstab.begin(), fstab.end(),
- [](const auto& entry) {
- return !entry.fs_mgr_flags.first_stage_mount;
- }),
- fstab.end());
- } else {
- LOG(INFO) << "Failed to fstab for first stage mount";
- }
- }
- return fstab;
- }
-
- bool FirstStageMount::DoFirstStageMount() {
- if (!IsDmLinearEnabled() && fstab_.empty()) {
- // Nothing to mount.
- LOG(INFO) << "First stage mount skipped (missing/incompatible/empty fstab in device tree)";
- return true;
- }
-
- if (!InitDevices()) return false;
-
- if (!MountPartitions()) return false;
-
- return true;
- }
-
- bool FirstStageMount::InitDevices() {
- std::set<std::string> devices;
- GetSuperDeviceName(&devices);
-
- if (!GetDmVerityDevices(&devices)) {
- return false;
- }
- if (!InitRequiredDevices(std::move(devices))) {
- return false;
- }
-
- if (IsDmLinearEnabled()) {
- auto super_symlink = "/dev/block/by-name/"s + super_partition_name_;
- if (!android::base::Realpath(super_symlink, &super_path_)) {
- PLOG(ERROR) << "realpath failed: " << super_symlink;
- return false;
- }
- }
- return true;
- }
-
- void FirstStageMount::GetSuperDeviceName(std::set<std::string>* devices) {
- // Add any additional devices required for dm-linear mappings.
- if (!IsDmLinearEnabled()) {
- return;
- }
-
- devices->emplace(super_partition_name_);
- }
-
- FirstStageMount::FirstStageMount(Fstab fstab) : need_dm_verity_(false), fstab_(std::move(fstab)) {
- super_partition_name_ = fs_mgr_get_super_partition_name(); //???
- }
-
- // Creates devices with uevent->partition_name matching ones in the given set.
- // Found partitions will then be removed from it for the subsequent member
- // function to check which devices are NOT created.
- bool FirstStageMount::InitRequiredDevices(std::set<std::string> devices) {
- //BlockDevInitializer block_dev_init_;
- //往/sys目录下的所有设备发送uevent事件,创建device-mapper设备节点
- if (!block_dev_init_.InitDeviceMapper()) { //???
- return false;
- }
- if (devices.empty()) {
- return true;
- }
- //创建dts中的vbmeta,vbmeta_system,vbmeta_vendor,boot,super分区设备
- return block_dev_init_.InitDevices(std::move(devices)); //???
- }
-
由于对GetSuperDeviceName不太明白,搜到如下文章 android R启动找不到super分区问题
- //system/core/fs_mgr/fs_mgr_fstab.cpp
- // Returns fstab entries parsed from the device tree if they exist
- bool ReadFstabFromDt(Fstab* fstab, bool log) {
- std::string fstab_buf = ReadFstabFromDt();
- if (fstab_buf.empty()) {
- if (log) LINFO << __FUNCTION__ << "(): failed to read fstab from dt";
- return false;
- }
-
- std::unique_ptr<FILE, decltype(&fclose)> fstab_file(
- fmemopen(static_cast<void*>(const_cast<char*>(fstab_buf.c_str())),
- fstab_buf.length(), "r"), fclose);
- if (!fstab_file) {
- if (log) PERROR << __FUNCTION__ << "(): failed to create a file stream for fstab dt";
- return false;
- }
-
- if (!ReadFstabFile(fstab_file.get(), false, fstab)) {
- if (log) {
- LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:" << std::endl
- << fstab_buf;
- }
- return false;
- }
-
- #ifndef NO_SKIP_MOUNT
- SkipMountingPartitions(fstab);
- #endif
-
- return true;
- }
-
- std::string ReadFstabFromDt() {
- if (!is_dt_compatible() || !IsDtFstabCompatible()) {
- return {};
- }
-
- //const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android/");
- //get_android_dt_dir 获取kernel命令行 "androidboot.android_dt_dir" 的键值,没有的话用kDefaultAndroidDtDir
- //kernel cmdline ----> cat /proc/cmdline
- std::string fstabdir_name = get_android_dt_dir() + "/fstab";
- std::unique_ptr<DIR, int (*)(DIR*)> fstabdir(opendir(fstabdir_name.c_str()), closedir);
- if (!fstabdir) return {}; //553没有dt fstab 直接返回
-
- dirent* dp;
- // Each element in fstab_dt_entries is <mount point, the line format in fstab file>.
- std::vector<std::pair<std::string, std::string>> fstab_dt_entries;
- while ((dp = readdir(fstabdir.get())) != NULL) {
- // skip over name, compatible and .
- if (dp->d_type != DT_DIR || dp->d_name[0] == '.') continue;
-
- // create <dev> <mnt_point> <type> <mnt_flags> <fsmgr_flags>\n
- std::vector<std::string> fstab_entry;
- std::string file_name;
- std::string value;
- // skip a partition entry if the status property is present and not set to ok
- file_name = android::base::StringPrintf("%s/%s/status", fstabdir_name.c_str(), dp->d_name);
- if (ReadDtFile(file_name, &value)) {
- if (value != "okay" && value != "ok") {
- LINFO << "dt_fstab: Skip disabled entry for partition " << dp->d_name;
- continue;
- }
- }
-
- file_name = android::base::StringPrintf("%s/%s/dev", fstabdir_name.c_str(), dp->d_name);
- if (!ReadDtFile(file_name, &value)) {
- LERROR << "dt_fstab: Failed to find device for partition " << dp->d_name;
- return {};
- }
- fstab_entry.push_back(value);
-
- std::string mount_point;
- file_name =
- android::base::StringPrintf("%s/%s/mnt_point", fstabdir_name.c_str(), dp->d_name);
- if (ReadDtFile(file_name, &value)) {
- LINFO << "dt_fstab: Using a specified mount point " << value << " for " << dp->d_name;
- mount_point = value;
- } else {
- mount_point = android::base::StringPrintf("/%s", dp->d_name);
- }
- fstab_entry.push_back(mount_point);
-
- file_name = android::base::StringPrintf("%s/%s/type", fstabdir_name.c_str(), dp->d_name);
- if (!ReadDtFile(file_name, &value)) {
- LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
- return {};
- }
- fstab_entry.push_back(value);
-
- file_name = android::base::StringPrintf("%s/%s/mnt_flags", fstabdir_name.c_str(), dp->d_name);
- if (!ReadDtFile(file_name, &value)) {
- LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
- return {};
- }
- fstab_entry.push_back(value);
-
- file_name = android::base::StringPrintf("%s/%s/fsmgr_flags", fstabdir_name.c_str(), dp->d_name);
- if (!ReadDtFile(file_name, &value)) {
- LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
- return {};
- }
- fstab_entry.push_back(value);
- // Adds a fstab_entry to fstab_dt_entries, to be sorted by mount_point later.
- fstab_dt_entries.emplace_back(mount_point, android::base::Join(fstab_entry, " "));
- }
-
- // Sort fstab_dt entries, to ensure /vendor is mounted before /vendor/abc is attempted.
- std::sort(fstab_dt_entries.begin(), fstab_dt_entries.end(),
- [](const auto& a, const auto& b) { return a.first < b.first; });
-
- std::string fstab_result;
- for (const auto& [_, dt_entry] : fstab_dt_entries) {
- fstab_result += dt_entry + "\n";
- }
- return fstab_result;
- }
-
- // 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) { //recovery 模式
- 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();
- }
-
- // Identify path to fstab file. Lookup is based on pattern
- // fstab.<fstab_suffix>, fstab.<hardware>, fstab.<hardware.platform> in
- // folders /odm/etc, vendor/etc, or /.
- std::string GetFstabPath() {
- for (const char* prop : {"fstab_suffix", "hardware", "hardware.platform"}) {
- std::string suffix;
-
- //[ro.boot.hardware]: [HNR553T] 只有hardware满足条件
- if (!fs_mgr_get_boot_config(prop, &suffix)) continue;
-
- for (const char* prefix : {"/odm/etc/fstab.", "/vendor/etc/fstab.", "/fstab."}) {
- std::string fstab_path = prefix + suffix;
- if (access(fstab_path.c_str(), F_OK) == 0) {
- return fstab_path;
- }
- }
- }
-
- return "";
- }
HNR553T:/proc/device-tree/firmware/android # ls
compatible name vbmeta553 的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 directory1|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_2c10HNR553T:/ # 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,checkHNR553T:/ # 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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。