diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h index a711340fa..f6e967653 100644 --- a/init/host_init_stubs.h +++ b/init/host_init_stubs.h @@ -45,6 +45,7 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value, const std::string& source_context, const ucred& cr, std::string* error); // reboot_utils.h +inline void SetFatalRebootTarget() {} inline void __attribute__((noreturn)) InitFatalReboot() { abort(); } diff --git a/init/reboot_utils.cpp b/init/reboot_utils.cpp index 4524f6983..d1a712f2e 100644 --- a/init/reboot_utils.cpp +++ b/init/reboot_utils.cpp @@ -32,6 +32,27 @@ namespace android { namespace init { +static std::string init_fatal_reboot_target = "bootloader"; + +void SetFatalRebootTarget() { + std::string cmdline; + android::base::ReadFileToString("/proc/cmdline", &cmdline); + cmdline = android::base::Trim(cmdline); + + const char kRebootTargetString[] = "androidboot.init_fatal_reboot_target="; + auto start_pos = cmdline.find(kRebootTargetString); + if (start_pos == std::string::npos) { + return; // We already default to bootloader if no setting is provided. + } + start_pos += sizeof(kRebootTargetString) - 1; + + auto end_pos = cmdline.find(' ', start_pos); + // if end_pos isn't found, then we've run off the end, but this is okay as this is the last + // entry, and -1 is a valid size for string::substr(); + auto size = end_pos == std::string::npos ? -1 : end_pos - start_pos; + init_fatal_reboot_target = cmdline.substr(start_pos, size); +} + bool IsRebootCapable() { if (!CAP_IS_SUPPORTED(CAP_SYS_BOOT)) { PLOG(WARNING) << "CAP_SYS_BOOT is not supported"; @@ -85,13 +106,13 @@ void __attribute__((noreturn)) InitFatalReboot() { if (pid == -1) { // Couldn't fork, don't even try to backtrace, just reboot. - RebootSystem(ANDROID_RB_RESTART2, "bootloader"); + RebootSystem(ANDROID_RB_RESTART2, init_fatal_reboot_target); } else if (pid == 0) { // Fork a child for safety, since we always want to shut down if something goes wrong, but // its worth trying to get the backtrace, even in the signal handler, since typically it // does work despite not being async-signal-safe. sleep(5); - RebootSystem(ANDROID_RB_RESTART2, "bootloader"); + RebootSystem(ANDROID_RB_RESTART2, init_fatal_reboot_target); } // In the parent, let's try to get a backtrace then shutdown. @@ -103,7 +124,7 @@ void __attribute__((noreturn)) InitFatalReboot() { for (size_t i = 0; i < backtrace->NumFrames(); i++) { LOG(ERROR) << backtrace->FormatFrameData(i); } - RebootSystem(ANDROID_RB_RESTART2, "bootloader"); + RebootSystem(ANDROID_RB_RESTART2, init_fatal_reboot_target); } void InstallRebootSignalHandlers() { diff --git a/init/reboot_utils.h b/init/reboot_utils.h index c4d97d57b..3fd969e69 100644 --- a/init/reboot_utils.h +++ b/init/reboot_utils.h @@ -21,6 +21,7 @@ namespace android { namespace init { +void SetFatalRebootTarget(); // Determines whether the system is capable of rebooting. This is conservative, // so if any of the attempts to determine this fail, it will still return true. bool IsRebootCapable(); diff --git a/init/util.cpp b/init/util.cpp index 790ab927a..63d2d4442 100644 --- a/init/util.cpp +++ b/init/util.cpp @@ -468,6 +468,7 @@ void SetStdioToDevNull(char** argv) { } void InitKernelLogging(char** argv) { + SetFatalRebootTarget(); android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter); }