Merge "init: make fatal reboot target configurable" into qt-dev
am: 4d63d1b7bb

Change-Id: I0b2e40dc8bc23251b71e91abcbecee7c5fc643f0
diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h
index a711340..f6e9676 100644
--- a/init/host_init_stubs.h
+++ b/init/host_init_stubs.h
@@ -45,6 +45,7 @@
                            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 4524f69..d1a712f 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 @@
 
     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 @@
     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 c4d97d5..3fd969e 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 790ab92..63d2d44 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -468,6 +468,7 @@
 }
 
 void InitKernelLogging(char** argv) {
+    SetFatalRebootTarget();
     android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
 }