Merge changes from topic "multi-kernel-mod-dirs" into rvc-dev
* changes: first_stage_init: support kernel module directories add libmodprobe api to query the number of modules loaded
This commit is contained in:
commit
0917ad0467
5 changed files with 80 additions and 11 deletions
|
@ -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 {
|
||||
|
|
|
@ -34,6 +34,8 @@ class Modprobe {
|
|||
bool GetAllDependencies(const std::string& module, std::vector<std::string>* pre_dependencies,
|
||||
std::vector<std::string>* dependencies,
|
||||
std::vector<std::string>* post_dependencies);
|
||||
void ResetModuleCount() { module_count_ = 0; }
|
||||
int GetModuleCount() { return module_count_; }
|
||||
void EnableBlacklist(bool enable);
|
||||
void EnableVerbose(bool enable);
|
||||
|
||||
|
@ -65,5 +67,6 @@ class Modprobe {
|
|||
std::unordered_map<std::string, std::string> module_options_;
|
||||
std::set<std::string> module_blacklist_;
|
||||
std::unordered_set<std::string> module_loaded_;
|
||||
int module_count_ = 0;
|
||||
bool blacklist_enabled = false;
|
||||
};
|
||||
|
|
|
@ -63,6 +63,7 @@ bool Modprobe::Insmod(const std::string& path_name, const std::string& parameter
|
|||
|
||||
LOG(INFO) << "Loaded kernel module " << path_name;
|
||||
module_loaded_.emplace(canonical_name);
|
||||
module_count_++;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ bool Modprobe::Insmod(const std::string& path_name, const std::string& parameter
|
|||
}
|
||||
|
||||
modules_loaded.emplace_back(path_name + options);
|
||||
module_count_++;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -161,6 +161,7 @@ TEST(libmodprobe, Test) {
|
|||
|
||||
EXPECT_TRUE(modules_loaded == expected_modules_loaded);
|
||||
|
||||
EXPECT_TRUE(m.GetModuleCount() == 15);
|
||||
EXPECT_TRUE(m.Remove("test4"));
|
||||
|
||||
GTEST_LOG_(INFO) << "Expected modules loaded after removing test4 (in order):";
|
||||
|
|
Loading…
Reference in a new issue