first_stage_init: add console
Start and wait on a console if androidboot.first_stage_console=1 is present on the kernel command line. This only works on eng and userdebug builds. Change-Id: I978e9390a89509431b399ea58b284736b27eeb1b
This commit is contained in:
parent
c538656d7d
commit
d75f30a4f0
3 changed files with 58 additions and 4 deletions
|
|
@ -26,6 +26,7 @@ cc_defaults {
|
|||
"-Wextra",
|
||||
"-Wno-unused-parameter",
|
||||
"-Werror",
|
||||
"-DALLOW_FIRST_STAGE_CONSOLE=0",
|
||||
"-DALLOW_LOCAL_PROP_OVERRIDE=0",
|
||||
"-DALLOW_PERMISSIVE_SELINUX=0",
|
||||
"-DREBOOT_BOOTLOADER_ON_PANIC=0",
|
||||
|
|
@ -36,6 +37,8 @@ cc_defaults {
|
|||
product_variables: {
|
||||
debuggable: {
|
||||
cppflags: [
|
||||
"-UALLOW_FIRST_STAGE_CONSOLE",
|
||||
"-DALLOW_FIRST_STAGE_CONSOLE=1",
|
||||
"-UALLOW_LOCAL_PROP_OVERRIDE",
|
||||
"-DALLOW_LOCAL_PROP_OVERRIDE=1",
|
||||
"-UALLOW_PERMISSIVE_SELINUX",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ LOCAL_PATH:= $(call my-dir)
|
|||
|
||||
ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
|
||||
init_options += \
|
||||
-DALLOW_FIRST_STAGE_CONSOLE=1 \
|
||||
-DALLOW_LOCAL_PROP_OVERRIDE=1 \
|
||||
-DALLOW_PERMISSIVE_SELINUX=1 \
|
||||
-DREBOOT_BOOTLOADER_ON_PANIC=1 \
|
||||
|
|
@ -15,6 +16,7 @@ init_options += \
|
|||
-DDUMP_ON_UMOUNT_FAILURE=1
|
||||
else
|
||||
init_options += \
|
||||
-DALLOW_FIRST_STAGE_CONSOLE=0 \
|
||||
-DALLOW_LOCAL_PROP_OVERRIDE=0 \
|
||||
-DALLOW_PERMISSIVE_SELINUX=0 \
|
||||
-DREBOOT_BOOTLOADER_ON_PANIC=0 \
|
||||
|
|
|
|||
|
|
@ -24,10 +24,12 @@
|
|||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/chrono_utils.h>
|
||||
|
|
@ -92,9 +94,50 @@ void FreeRamdisk(DIR* dir, dev_t dev) {
|
|||
}
|
||||
}
|
||||
|
||||
bool ForceNormalBoot() {
|
||||
std::string cmdline;
|
||||
android::base::ReadFileToString("/proc/cmdline", &cmdline);
|
||||
void StartConsole() {
|
||||
if (mknod("/dev/console", S_IFCHR | 0600, makedev(5, 1))) {
|
||||
PLOG(ERROR) << "unable to create /dev/console";
|
||||
return;
|
||||
}
|
||||
pid_t pid = fork();
|
||||
if (pid != 0) {
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
LOG(ERROR) << "console shell exited with status " << status;
|
||||
return;
|
||||
}
|
||||
int fd = -1;
|
||||
int tries = 10;
|
||||
// The device driver for console may not be ready yet so retry for a while in case of failure.
|
||||
while (tries--) {
|
||||
fd = open("/dev/console", O_RDWR);
|
||||
if (fd != -1) {
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
if (fd == -1) {
|
||||
LOG(ERROR) << "Could not open /dev/console, errno = " << errno;
|
||||
_exit(127);
|
||||
}
|
||||
ioctl(fd, TIOCSCTTY, 0);
|
||||
dup2(fd, 0);
|
||||
dup2(fd, 1);
|
||||
dup2(fd, 2);
|
||||
close(fd);
|
||||
|
||||
const char* path = "/system/bin/sh";
|
||||
const char* args[] = {path, nullptr};
|
||||
int rv = execv(path, const_cast<char**>(args));
|
||||
LOG(ERROR) << "unable to execv, returned " << rv << " errno " << errno;
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
bool FirstStageConsole(const std::string& cmdline) {
|
||||
return cmdline.find("androidboot.first_stage_console=1") != std::string::npos;
|
||||
}
|
||||
|
||||
bool ForceNormalBoot(const std::string& cmdline) {
|
||||
return cmdline.find("androidboot.force_normal_boot=1") != std::string::npos;
|
||||
}
|
||||
|
||||
|
|
@ -127,6 +170,8 @@ int FirstStageMain(int argc, char** argv) {
|
|||
#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));
|
||||
|
|
@ -198,7 +243,11 @@ int FirstStageMain(int argc, char** argv) {
|
|||
LOG(FATAL) << "Failed to load kernel modules";
|
||||
}
|
||||
|
||||
if (ForceNormalBoot()) {
|
||||
if (ALLOW_FIRST_STAGE_CONSOLE && FirstStageConsole(cmdline)) {
|
||||
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.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue