Merge "first_stage_init: support kernel module directories" am: dc9acdd221 am: f517b00dce

Original change: https://android-review.googlesource.com/c/platform/system/core/+/1319048

Change-Id: I8a3774e14d24c3559b8f50e9aea5f4c33cf86548
This commit is contained in:
Treehugger Robot 2020-06-03 19:34:23 +00:00 committed by Automerger Merge Worker
commit 2f724342ff

View file

@ -24,6 +24,7 @@
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <filesystem>
@ -99,6 +100,77 @@ bool ForceNormalBoot(const std::string& cmdline) {
} // namespace
std::string GetModuleLoadList(bool recovery, const std::string& dir_path) {
auto module_load_file = "modules.load";
if (recovery) {
struct stat fileStat;
std::string recovery_load_path = dir_path + "/modules.load.recovery";
if (!stat(recovery_load_path.c_str(), &fileStat)) {
module_load_file = "modules.load.recovery";
}
}
return module_load_file;
}
#define MODULE_BASE_DIR "/lib/modules"
bool LoadKernelModules(bool recovery, bool want_console) {
struct utsname uts;
if (uname(&uts)) {
LOG(FATAL) << "Failed to get kernel version.";
}
int major, minor;
if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
LOG(FATAL) << "Failed to parse kernel version " << uts.release;
}
std::unique_ptr<DIR, decltype(&closedir)> base_dir(opendir(MODULE_BASE_DIR), closedir);
if (!base_dir) {
LOG(INFO) << "Unable to open /lib/modules, skipping module loading.";
return true;
}
dirent* entry;
std::vector<std::string> module_dirs;
while ((entry = readdir(base_dir.get()))) {
if (entry->d_type != DT_DIR) {
continue;
}
int dir_major, dir_minor;
if (sscanf(entry->d_name, "%d.%d", &dir_major, &dir_minor) != 2 || dir_major != major ||
dir_minor != minor) {
continue;
}
module_dirs.emplace_back(entry->d_name);
}
// Sort the directories so they are iterated over during module loading
// in a consistent order. Alphabetical sorting is fine here because the
// kernel version at the beginning of the directory name must match the
// current kernel version, so the sort only applies to a label that
// follows the kernel version, for example /lib/modules/5.4 vs.
// /lib/modules/5.4-gki.
std::sort(module_dirs.begin(), module_dirs.end());
for (const auto& module_dir : module_dirs) {
std::string dir_path = MODULE_BASE_DIR "/";
dir_path.append(module_dir);
Modprobe m({dir_path}, GetModuleLoadList(recovery, dir_path));
bool retval = m.LoadListedModules(!want_console);
int modules_loaded = m.GetModuleCount();
if (modules_loaded > 0) {
return retval;
}
}
Modprobe m({MODULE_BASE_DIR}, GetModuleLoadList(recovery, MODULE_BASE_DIR));
bool retval = m.LoadListedModules(!want_console);
int modules_loaded = m.GetModuleCount();
if (modules_loaded > 0) {
return retval;
}
return true;
}
int FirstStageMain(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
@ -190,18 +262,9 @@ int FirstStageMain(int argc, char** argv) {
old_root_dir.reset();
}
std::string module_load_file = "modules.load";
if (IsRecoveryMode() && !ForceNormalBoot(cmdline)) {
struct stat fileStat;
std::string recovery_load_path = "/lib/modules/modules.load.recovery";
if (!stat(recovery_load_path.c_str(), &fileStat)) {
module_load_file = "modules.load.recovery";
}
}
Modprobe m({"/lib/modules"}, module_load_file);
auto want_console = ALLOW_FIRST_STAGE_CONSOLE ? FirstStageConsole(cmdline) : 0;
if (!m.LoadListedModules(!want_console)) {
if (!LoadKernelModules(IsRecoveryMode() && !ForceNormalBoot(cmdline), want_console)) {
if (want_console != FirstStageConsoleParam::DISABLED) {
LOG(ERROR) << "Failed to load kernel modules, starting console";
} else {