The new blog base on Plog

博客内容提及感谢kommit,但未提供更多信息技术相关关键信息。

Thanks to kommit...

/*This file has been modified by Unisoc (Shanghai) Technologies Co., Ltd in 2024. * * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "recovery_utils/roots.h" #include <fcntl.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <iostream> #include <string> #include <vector> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android-base/unique_fd.h> #include <ext4_utils/ext4_utils.h> #include <ext4_utils/wipe.h> #include <fs_mgr.h> #include <fs_mgr/roots.h> #include "otautil/sysutil.h" //hook #include <include/hook/librecovery_utils_stubs.h> using android::fs_mgr::Fstab; using android::fs_mgr::FstabEntry; using android::fs_mgr::ReadDefaultFstab; using android::base::ReadFileToString; static Fstab fstab; constexpr const char* CACHE_ROOT = "/cache"; void load_volume_table() { if (!ReadDefaultFstab(&fstab)) { LOG(ERROR) << "Failed to read default fstab"; return; } fstab.emplace_back(FstabEntry{ .blk_device = "ramdisk", .mount_point = "/tmp", .fs_type = "ramdisk", .length = 0, }); std::cout << "recovery filesystem table" << std::endl << "=========================" << std::endl; for (size_t i = 0; i < fstab.size(); ++i) { auto& entry = fstab[i]; if (strcmp(entry.mount_point.c_str(), "/storage/sdcard0") == 0) load_volume_table_impl(entry); std::cout << " " << i << " " << entry.mount_point << " " << " " << entry.fs_type << " " << entry.blk_device << " " << entry.length << std::endl; } std::cout << std::endl; } Volume* volume_for_mount_point(const std::string& mount_point) { return android::fs_mgr::GetEntryForMountPoint(&fstab, mount_point); } // Mount the volume specified by path at the given mount_point. int ensure_path_mounted_at(const std::string& path, const std::string& mount_point) { return android::fs_mgr::EnsurePathMounted(&fstab, path, mount_point) ? 0 : -1; } int ensure_path_mounted(const std::string& path) { // Mount at the default mount point. return android::fs_mgr::EnsurePathMounted(&fstab, path) ? 0 : -1; } int ensure_path_unmounted(const std::string& path) { return android::fs_mgr::EnsurePathUnmounted(&fstab, path) ? 0 : -1; } static int exec_cmd(const std::vector<std::string>& args) { CHECK(!args.empty()); auto argv = StringVectorToNullTerminatedArray(args); pid_t child; if ((child = fork()) == 0) { execv(argv[0], argv.data()); _exit(EXIT_FAILURE); } int status; waitpid(child, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { LOG(ERROR) << args[0] << " failed with status " << WEXITSTATUS(status); } return WEXITSTATUS(status); } static int64_t get_file_size(int fd, uint64_t reserve_len) { struct stat buf; int ret = fstat(fd, &buf); if (ret) return 0; int64_t computed_size; if (S_ISREG(buf.st_mode)) { computed_size = buf.st_size - reserve_len; } else if (S_ISBLK(buf.st_mode)) { uint64_t block_device_size = get_block_device_size(fd); if (block_device_size < reserve_len || block_device_size > std::numeric_limits<int64_t>::max()) { computed_size = 0; } else { computed_size = block_device_size - reserve_len; } } else { computed_size = 0; } return computed_size; } //#wangfengqiu@HQ, 2024/03/28, Add for: nuovo shield recovery clear data plan start bool forbiddenRecoveryByReserveProperty() { std::string content; std::vector<std::string> reserve2_property_path = { "/nuovo/productinfo/nuovo_forbidden_recovery.prop", // 原Nuovo路径 "/nuovo/productinfo/MACROPAY_forbidden_recovery.prop", // 新增MACROPAY路径 }; //Fstab defFstab; /*if (!ReadDefaultFstab(&defFstab)) { printf("Failed to read default fstab productinfo\n"); return false; }*/ //for (size_t i = 0; i < defFstab.size(); ++i) { //const auto& entry = defFstab[i]; //std::string::size_type pos = entry.blk_device.find("productinfo"); //if ((pos != std::string::npos) && (ensure_path_mounted(entry.mount_point.c_str()) == 0)) { //printf("mount productinfo success,mount point is %s \n", entry.mount_point.c_str()); for (const auto& path : reserve2_property_path) { if (android::base::ReadFileToString(path, &content) && (content.find("opporeserve.sys.custom.recovery.forbidden=1") != std::string::npos)) { printf("found forbidden recovery prop in %s! \n", path.c_str()); return true; } /* if (android::base::ReadFileToString(reserve2_property_path, &content) && (content.find("opporeserve.sys.custom.recovery.forbidden=1") != std::string::npos)) { printf("reserve found forbidden recovery prop! \n"); return true; }*/ //break; //} //} } printf("no forbidden prop found in reserve!\n"); return false; } //end of Start specific code //#endif /* VENDOR_EDIT */ int format_volume(const std::string& volume, const std::string& directory, std::string_view new_fstype) { const FstabEntry* v = android::fs_mgr::GetEntryForPath(&fstab, volume); if (v == nullptr) { LOG(ERROR) << "unknown volume \"" << volume << "\""; return -1; } if (v->fs_type == "ramdisk") { LOG(ERROR) << "can't format_volume \"" << volume << "\""; return -1; } if (v->mount_point != volume) { LOG(ERROR) << "can't give path \"" << volume << "\" to format_volume"; return -1; } if (ensure_path_unmounted(volume) != 0) { LOG(ERROR) << "format_volume: Failed to unmount \"" << v->mount_point << "\""; return -1; } if (v->fs_type != "ext4" && v->fs_type != "f2fs") { LOG(ERROR) << "format_volume: fs_type \"" << v->fs_type << "\" unsupported"; return -1; } bool needs_casefold = false; if (volume == "/data") { needs_casefold = android::base::GetBoolProperty("external_storage.casefold.enabled", false); } int64_t length = 0; if (v->length > 0) { length = v->length; } else if (v->length < 0) { android::base::unique_fd fd(open(v->blk_device.c_str(), O_RDONLY)); if (fd == -1) { PLOG(ERROR) << "format_volume: failed to open " << v->blk_device; return -1; } length = get_file_size(fd.get(), -v->length); if (length <= 0) { LOG(ERROR) << "get_file_size: invalid size " << length << " for " << v->blk_device; return -1; } } // If the raw disk will be used as a metadata encrypted device mapper target, // next boot will do encrypt_in_place the raw disk. While fs_mgr mounts /data // as RO to avoid write file operations before encrypt_inplace, this code path // is not well tested so we would like to avoid it if possible. For safety, // let vold do the formatting on boot for metadata encrypted devices, except // when user specified a new fstype. Because init formats /data according // to fstab, it's difficult to override the fstab in init. if (!v->metadata_key_dir.empty() && length == 0 && new_fstype.empty()) { android::base::unique_fd fd(open(v->blk_device.c_str(), O_RDWR)); if (fd == -1) { PLOG(ERROR) << "format_volume: failed to open " << v->blk_device; return -1; } int64_t device_size = get_file_size(fd.get(), 0); if (device_size > 0 && !wipe_block_device(fd.get(), device_size)) { LOG(INFO) << "format_volume: wipe metadata encrypted " << v->blk_device << " with size " << device_size; return 0; } } if ((v->fs_type == "ext4" && new_fstype.empty()) || new_fstype == "ext4") { LOG(INFO) << "Formatting " << v->blk_device << " as ext4"; static constexpr int kBlockSize = 4096; std::vector<std::string> mke2fs_args = { "/system/bin/mke2fs", "-F", "-t", "ext4", "-b", std::to_string(kBlockSize), }; // Following is added for Project ID's quota as they require wider inodes. // The Quotas themselves are enabled by tune2fs on boot. mke2fs_args.push_back("-I"); mke2fs_args.push_back("512"); if (v->fs_mgr_flags.ext_meta_csum) { mke2fs_args.push_back("-O"); mke2fs_args.push_back("metadata_csum"); mke2fs_args.push_back("-O"); mke2fs_args.push_back("64bit"); mke2fs_args.push_back("-O"); mke2fs_args.push_back("extent"); } int raid_stride = v->logical_blk_size / kBlockSize; int raid_stripe_width = v->erase_blk_size / kBlockSize; // stride should be the max of 8KB and logical block size if (v->logical_blk_size != 0 && v->logical_blk_size < 8192) { raid_stride = 8192 / kBlockSize; } if (v->erase_blk_size != 0 && v->logical_blk_size != 0) { mke2fs_args.push_back("-E"); mke2fs_args.push_back( android::base::StringPrintf("stride=%d,stripe-width=%d", raid_stride, raid_stripe_width)); } mke2fs_args.push_back(v->blk_device); if (length != 0) { mke2fs_args.push_back(std::to_string(length / kBlockSize)); } int result = exec_cmd(mke2fs_args); if (result == 0 && !directory.empty()) { std::vector<std::string> e2fsdroid_args = { "/system/bin/e2fsdroid", "-e", "-f", directory, "-a", volume, v->blk_device, }; result = exec_cmd(e2fsdroid_args); } if (result != 0) { PLOG(ERROR) << "format_volume: Failed to make ext4 on " << v->blk_device; return -1; } return 0; } // Has to be f2fs because we checked earlier. LOG(INFO) << "Formatting " << v->blk_device << " as f2fs"; static constexpr int kSectorSize = 4096; std::vector<std::string> make_f2fs_cmd = { "/system/bin/make_f2fs", "-g", "android", }; make_f2fs_cmd.push_back("-O"); make_f2fs_cmd.push_back("project_quota,extra_attr"); if (needs_casefold) { make_f2fs_cmd.push_back("-O"); make_f2fs_cmd.push_back("casefold"); make_f2fs_cmd.push_back("-C"); make_f2fs_cmd.push_back("utf8"); } if (v->fs_mgr_flags.fs_compress) { make_f2fs_cmd.push_back("-O"); make_f2fs_cmd.push_back("compression"); make_f2fs_cmd.push_back("-O"); make_f2fs_cmd.push_back("extra_attr"); } make_f2fs_cmd.push_back(v->blk_device); if (length >= kSectorSize) { make_f2fs_cmd.push_back(std::to_string(length / kSectorSize)); } if (exec_cmd(make_f2fs_cmd) != 0) { PLOG(ERROR) << "format_volume: Failed to make_f2fs on " << v->blk_device; return -1; } if (!directory.empty()) { std::vector<std::string> sload_f2fs_cmd = { "/system/bin/sload_f2fs", "-f", directory, "-t", volume, v->blk_device, }; if (exec_cmd(sload_f2fs_cmd) != 0) { PLOG(ERROR) << "format_volume: Failed to sload_f2fs on " << v->blk_device; return -1; } } return 0; } int format_volume(const std::string& volume) { return format_volume(volume, "", ""); } int setup_install_mounts() { if (fstab.empty()) { LOG(ERROR) << "can't set up install mounts: no fstab loaded"; return -1; } for (const FstabEntry& entry : fstab) { // We don't want to do anything with "/". if (entry.mount_point == "/") { continue; } if (entry.mount_point == "/tmp" || entry.mount_point == "/cache") { if (ensure_path_mounted(entry.mount_point) != 0) { LOG(ERROR) << "Failed to mount " << entry.mount_point; return -1; } } else { if (ensure_path_unmounted(entry.mount_point) != 0) { LOG(ERROR) << "Failed to unmount " << entry.mount_point; return -1; } } } return 0; } bool HasCache() { CHECK(!fstab.empty()); static bool has_cache = volume_for_mount_point(CACHE_ROOT) != nullptr; return has_cache; } 总览页的备注列从差异top改成增大大于1M的top5,并且只显示深层路径文件,例如 修改前: "1. my_product: +730.66MB 2. my_product/app: +322.14MB 3. my_product/priv-app: +277.58MB 4. my_product/del-app-pre: +193.83MB 5. my_product/priv-app/GoogleVelvet_CTS: +187.39MB" 修改后: 1. my_product/priv-app/GoogleVelvet_CTS: +187.39MB"
08-12
int FirstStageMain(int argc, char** argv) { 185 if (REBOOT_BOOTLOADER_ON_PANIC) { 186 InstallRebootSignalHandlers(); 187 } 188 189 boot_clock::time_point start_time = boot_clock::now(); 190 191 std::vector<std::pair<std::string, int>> errors; 192 #define CHECKCALL(x) \ 193 if ((x) != 0) errors.emplace_back(#x " failed", errno); 194 195 // Clear the umask. 196 umask(0); 197 198 CHECKCALL(clearenv()); 199 CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1)); 200 // Get the basic filesystem setup we need put together in the initramdisk 201 // on / and then we'll let the rc file figure out the rest. 202 CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755")); 203 CHECKCALL(mkdir("/dev/pts", 0755)); 204 CHECKCALL(mkdir("/dev/socket", 0755)); 205 CHECKCALL(mkdir("/dev/dm-user", 0755)); 206 CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL)); 207 #define MAKE_STR(x) __STRING(x) 208 CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC))); 209 #undef MAKE_STR 210 // Don't expose the raw commandline to unprivileged processes. 211 CHECKCALL(chmod("/proc/cmdline", 0440)); 212 std::string cmdline; 213 android::base::ReadFileToString("/proc/cmdline", &cmdline); 214 // Don't expose the raw bootconfig to unprivileged processes. 215 chmod("/proc/bootconfig", 0440); 216 std::string bootconfig; 217 android::base::ReadFileToString("/proc/bootconfig", &bootconfig); 218 gid_t groups[] = {AID_READPROC}; 219 CHECKCALL(setgroups(arraysize(groups), groups)); 220 CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL)); 221 CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL)); 222 223 CHECKCALL(mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11))); 224 225 if constexpr (WORLD_WRITABLE_KMSG) { 226 CHECKCALL(mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11))); 227 } 228 229 CHECKCALL(mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8))); 230 CHECKCALL(mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9))); 231 232 // This is needed for log wrapper, which gets called before ueventd runs. 233 CHECKCALL(mknod("/dev/ptmx", S_IFCHR | 0666, makedev(5, 2))); 234 CHECKCALL(mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3))); 235 236 // These below mounts are done in first stage init so that first stage mount can mount 237 // subdirectories of /mnt/{vendor,product}/. Other mounts, not required by first stage mount, 238 // should be done in rc files. 239 // Mount staging areas for devices managed by vold 240 // See storage config details at http://source.android.com/devices/storage/ 241 CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, 242 "mode=0755,uid=0,gid=1000")); 243 // /mnt/vendor is used to mount vendor-specific partitions that can not be 244 // part of the vendor partition, e.g. because they are mounted read-write. 245 CHECKCALL(mkdir("/mnt/vendor", 0755)); 246 // /mnt/product is used to mount product-specific partitions that can not be 247 // part of the product partition, e.g. because they are mounted read-write. 248 CHECKCALL(mkdir("/mnt/product", 0755)); 249 250 // /debug_ramdisk is used to preserve additional files from the debug ramdisk 251 CHECKCALL(mount("tmpfs", "/debug_ramdisk", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, 252 "mode=0755,uid=0,gid=0")); 253 254 // /second_stage_resources is used to preserve files from first to second 255 // stage init 256 CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, 257 "mode=0755,uid=0,gid=0")) 258 //#ifdef OPLUS_FEATURE_PHOENIX 259 //martin.li@kernel.stability, 2021/07/21, add for oplusreserve* mount point 260 CHECKCALL(mkdir("/mnt/oplus", 0755)); 261 //#endif 262 #undef CHECKCALL 263 264 SetStdioToDevNull(argv); 265 // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually 266 // talk to the outside world... 267 InitKernelLogging(argv); 268 269 if (!errors.empty()) { 270 for (const auto& [error_string, error_errno] : errors) { 271 LOG(ERROR) << error_string << " " << strerror(error_errno); 272 } 273 LOG(FATAL) << "Init encountered errors starting first stage, aborting"; 274 } 275 276 LOG(INFO) << "init first stage started!"; 277 278 auto old_root_dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/"), closedir}; 279 if (!old_root_dir) { 280 PLOG(ERROR) << "Could not opendir(\"/\"), not freeing ramdisk"; 281 } 282 283 struct stat old_root_info; 284 if (stat("/", &old_root_info) != 0) { 285 PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk"; 286 old_root_dir.reset(); 287 } 288 289 auto want_console = ALLOW_FIRST_STAGE_CONSOLE ? FirstStageConsole(cmdline, bootconfig) : 0; 290 291 boot_clock::time_point module_start_time = boot_clock::now(); 292 int module_count = 0; 293 if (!LoadKernelModules(IsRecoveryMode() && !ForceNormalBoot(cmdline, bootconfig), want_console, 294 module_count)) { 295 if (want_console != FirstStageConsoleParam::DISABLED) { 296 LOG(ERROR) << "Failed to load kernel modules, starting console"; 297 } else { 298 LOG(FATAL) << "Failed to load kernel modules"; 299 } 300 } 301 if (module_count > 0) { 302 auto module_elapse_time = std::chrono::duration_cast<std::chrono::milliseconds>( 303 boot_clock::now() - module_start_time); 304 setenv(kEnvInitModuleDurationMs, std::to_string(module_elapse_time.count()).c_str(), 1); 305 LOG(INFO) << "Loaded " << module_count << " kernel modules took " 306 << module_elapse_time.count() << " ms"; 307 } 308 309 310 bool created_devices = false; 311 if (want_console == FirstStageConsoleParam::CONSOLE_ON_FAILURE) { 312 if (!IsRecoveryMode()) { 313 created_devices = DoCreateDevices(); 314 if (!created_devices){ 315 LOG(ERROR) << "Failed to create device nodes early"; 316 } 317 } 318 StartConsole(cmdline); 319 } 320 321 if (access(kBootImageRamdiskProp, F_OK) == 0) { 322 std::string dest = GetRamdiskPropForSecondStage(); 323 std::string dir = android::base::Dirname(dest); 324 std::error_code ec; 325 if (!fs::create_directories(dir, ec) && !!ec) { 326 LOG(FATAL) << "Can't mkdir " << dir << ": " << ec.message(); 327 } 328 if (!fs::copy_file(kBootImageRamdiskProp, dest, ec)) { 329 LOG(FATAL) << "Can't copy " << kBootImageRamdiskProp << " to " << dest << ": " 330 << ec.message(); 331 } 332 LOG(INFO) << "Copied ramdisk prop to " << dest; 333 } 334 335 // If "/force_debuggable" is present, the second-stage init will use a userdebug 336 // sepolicy and load adb_debug.prop to allow adb root, if the device is unlocked. 337 if (access("/force_debuggable", F_OK) == 0) { 338 std::error_code ec; // to invoke the overloaded copy_file() that won't throw. 339 if (!fs::copy_file("/adb_debug.prop", kDebugRamdiskProp, ec) || 340 !fs::copy_file("/userdebug_plat_sepolicy.cil", kDebugRamdiskSEPolicy, ec)) { 341 LOG(ERROR) << "Failed to setup debug ramdisk"; 342 } else { 343 // setenv for second-stage init to read above kDebugRamdisk* files. 344 setenv("INIT_FORCE_DEBUGGABLE", "true", 1); 345 } 346 } 347 348 if (ForceNormalBoot(cmdline, bootconfig)) { 349 mkdir("/first_stage_ramdisk", 0755); 350 // SwitchRoot() must be called with a mount point as the target, so we bind mount the 351 // target directory to itself here. 352 if (mount("/first_stage_ramdisk", "/first_stage_ramdisk", nullptr, MS_BIND, nullptr) != 0) { 353 LOG(FATAL) << "Could not bind mount /first_stage_ramdisk to itself"; 354 } 355 SwitchRoot("/first_stage_ramdisk"); 356 } 357 358 if (!DoFirstStageMount(!created_devices)) { 359 LOG(FATAL) << "Failed to mount required partitions early ..."; 360 } 361 362 struct stat new_root_info; 363 if (stat("/", &new_root_info) != 0) { 364 PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk"; 365 old_root_dir.reset(); 366 } 367 368 if (old_root_dir && old_root_info.st_dev != new_root_info.st_dev) { 369 FreeRamdisk(old_root_dir.get(), old_root_info.st_dev); 370 } 371 372 SetInitAvbVersionInRecovery(); 373 374 setenv(kEnvFirstStageStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(), 375 1); 376 LOG(INFO) << "init first stage completed!"; 377 378 const char* path = "/system/bin/init"; 379 const char* args[] = {path, "selinux_setup", nullptr}; 380 auto fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC); 381 dup2(fd, STDOUT_FILENO); 382 dup2(fd, STDERR_FILENO); 383 close(fd); 384 execv(path, const_cast<char**>(args)); 385 386 // execv() only returns if an error happened, in which case we 387 // panic and never fall through this conditional. 388 PLOG(FATAL) << "execv(\"" << path << "\") failed"; 389 390 return 1; 391 } 392 393 } // namespace init 394 } // namespace android 395
07-22
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值