first_stage_init: add hook to exec a shell script
If the first stage console is being used, attempt to run /first_stage.sh immediately before the console is created. Bug: 154126020 Change-Id: I8b7431e7b8219afea295b120d7ea91751804bda6
This commit is contained in:
parent
c4793572f3
commit
a4bf2cee04
|
@ -41,6 +41,7 @@ init_device_sources = [
|
|||
"builtins.cpp",
|
||||
"devices.cpp",
|
||||
"firmware_handler.cpp",
|
||||
"first_stage_console.cpp",
|
||||
"first_stage_init.cpp",
|
||||
"first_stage_mount.cpp",
|
||||
"fscrypt_init_extensions.cpp",
|
||||
|
|
|
@ -50,6 +50,7 @@ LOCAL_CPPFLAGS := $(init_cflags)
|
|||
LOCAL_SRC_FILES := \
|
||||
block_dev_initializer.cpp \
|
||||
devices.cpp \
|
||||
first_stage_console.cpp \
|
||||
first_stage_init.cpp \
|
||||
first_stage_main.cpp \
|
||||
first_stage_mount.cpp \
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (C) 2020 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 "first_stage_console.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <android-base/chrono_utils.h>
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
|
||||
static void RunScript() {
|
||||
LOG(INFO) << "Attempting to run /first_stage.sh...";
|
||||
pid_t pid = fork();
|
||||
if (pid != 0) {
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
LOG(INFO) << "/first_stage.sh exited with status " << status;
|
||||
return;
|
||||
}
|
||||
const char* path = "/system/bin/sh";
|
||||
const char* args[] = {path, "/first_stage.sh", nullptr};
|
||||
int rv = execv(path, const_cast<char**>(args));
|
||||
LOG(ERROR) << "unable to execv /first_stage.sh, returned " << rv << " errno " << errno;
|
||||
}
|
||||
|
||||
namespace android {
|
||||
namespace init {
|
||||
|
||||
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 = 50; // should timeout after 5s
|
||||
// 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, STDIN_FILENO);
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
dup2(fd, STDERR_FILENO);
|
||||
close(fd);
|
||||
|
||||
RunScript();
|
||||
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;
|
||||
}
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace android {
|
||||
namespace init {
|
||||
|
||||
void StartConsole();
|
||||
bool FirstStageConsole(const std::string& cmdline);
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
|
@ -24,12 +24,10 @@
|
|||
#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>
|
||||
|
@ -39,6 +37,7 @@
|
|||
#include <private/android_filesystem_config.h>
|
||||
|
||||
#include "debug_ramdisk.h"
|
||||
#include "first_stage_console.h"
|
||||
#include "first_stage_mount.h"
|
||||
#include "reboot_utils.h"
|
||||
#include "switch_root.h"
|
||||
|
@ -94,49 +93,6 @@ void FreeRamdisk(DIR* dir, dev_t dev) {
|
|||
}
|
||||
}
|
||||
|
||||
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 = 50; // should timeout after 5s
|
||||
// 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, STDIN_FILENO);
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
dup2(fd, STDERR_FILENO);
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue