Skip to content

Commit

Permalink
More complete support for fstab in dt
Browse files Browse the repository at this point in the history
  • Loading branch information
topjohnwu committed May 4, 2020
1 parent 8ab0453 commit 0c99c4d
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 114 deletions.
10 changes: 7 additions & 3 deletions native/jni/init/getinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@

using namespace std;

#define DEFAULT_DT_DIR "/proc/device-tree/firmware/android"

static void parse_cmdline(const std::function<void (std::string_view, const char *)> &fn) {
char cmdline[4096];
int fd = open("/proc/cmdline", O_RDONLY | O_CLOEXEC);
int fd = xopen("/proc/cmdline", O_RDONLY | O_CLOEXEC);
cmdline[read(fd, cmdline, sizeof(cmdline))] = '\0';
close(fd);

Expand Down Expand Up @@ -125,7 +123,10 @@ void load_kernel_info(cmdline *cmd) {
} else if (key == "enter_recovery") {
enter_recovery = value[0] == '1';
} else if (key == "androidboot.hardware") {
strcpy(cmd->hardware, value);
kirin = strstr(value, "kirin") || strstr(value, "hi3660") || strstr(value, "hi6250");
} else if (key == "androidboot.hardware.platform") {
strcpy(cmd->hardware_plat, value);
}
});

Expand Down Expand Up @@ -154,8 +155,11 @@ void load_kernel_info(cmdline *cmd) {
if (cmd->dt_dir[0] == '\0')
strcpy(cmd->dt_dir, DEFAULT_DT_DIR);

LOGD("Device info:\n");
LOGD("skip_initramfs=[%d]\n", cmd->skip_initramfs);
LOGD("force_normal_boot=[%d]\n", cmd->force_normal_boot);
LOGD("slot=[%s]\n", cmd->slot);
LOGD("dt_dir=[%s]\n", cmd->dt_dir);
LOGD("hardware=[%s]\n", cmd->hardware);
LOGD("hardware.platform=[%s]\n", cmd->hardware_plat);
}
39 changes: 30 additions & 9 deletions native/jni/init/init.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@
#include <unistd.h>
#include <stdlib.h>
#include <vector>
#include <map>

#include <logging.hpp>

struct cmdline {
bool skip_initramfs;
bool force_normal_boot;
char slot[3];
char dt_dir[128];
char dt_dir[64];
char hardware[32];
char hardware_plat[32];
};

struct raw_data {
Expand All @@ -31,6 +34,30 @@ struct raw_data {
}
};

struct fstab_entry {
std::string dev;
std::string mnt_point;
std::string type;
std::string mnt_flags;
std::string fsmgr_flags;

fstab_entry() = default;
fstab_entry(const fstab_entry &o) = delete;
fstab_entry(fstab_entry &&o) = default;
};

#define INIT_SOCKET "MAGISKINIT"
#define DEFAULT_DT_DIR "/proc/device-tree/firmware/android"

void load_kernel_info(cmdline *cmd);
int dump_magisk(const char *path, mode_t mode);
int magisk_proxy_main(int argc, char *argv[]);
void setup_klog();
void setup_tmp(const char *path, const raw_data &self, const raw_data &config);

using str_pairs = std::initializer_list<std::pair<std::string_view, std::string_view>>;
int raw_data_patch(void *addr, size_t sz, str_pairs list);

/***************
* Base classes
***************/
Expand All @@ -52,6 +79,8 @@ class BaseInit {
cmd(cmd), argv(argv), mount_list{"/sys", "/proc"} {}
virtual ~BaseInit() = default;
virtual void start() = 0;
void read_dt_fstab(std::map<std::string_view, fstab_entry> &fstab);
void dt_early_mount();
};

class MagiskInit : public BaseInit {
Expand Down Expand Up @@ -158,11 +187,3 @@ class RootFSInit : public MagiskInit {
exec_init();
}
};

#define INIT_SOCKET "MAGISKINIT"

void load_kernel_info(cmdline *cmd);
int dump_magisk(const char *path, mode_t mode);
int magisk_proxy_main(int argc, char *argv[]);
void setup_klog();
void setup_tmp(const char *path, const raw_data &self, const raw_data &config);
140 changes: 84 additions & 56 deletions native/jni/init/mount.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <sys/sysmacros.h>
#include <string.h>
#include <stdio.h>
#include <libgen.h>
#include <vector>

#include <utils.hpp>
Expand All @@ -21,10 +22,6 @@ struct devinfo {

static vector<devinfo> dev_list;

static char partname[32];
static char fstype[32];
static char block_dev[64];

static void parse_device(devinfo *dev, const char *uevent) {
dev->partname[0] = '\0';
parse_prop_file(uevent, [=](string_view key, string_view value) -> bool {
Expand Down Expand Up @@ -55,6 +52,11 @@ static void collect_devices() {
}
}

static struct {
char partname[32];
char block_dev[64];
} blk_info;

static int64_t setup_block(bool write_block = true) {
if (dev_list.empty())
collect_devices();
Expand All @@ -63,13 +65,13 @@ static int64_t setup_block(bool write_block = true) {

for (int tries = 0; tries < 3; ++tries) {
for (auto &dev : dev_list) {
if (strcasecmp(dev.partname, partname) == 0) {
if (strcasecmp(dev.partname, blk_info.partname) == 0) {
if (write_block) {
sprintf(block_dev, "/dev/block/%s", dev.devname);
sprintf(blk_info.block_dev, "/dev/block/%s", dev.devname);
}
LOGD("Found %s: [%s] (%d, %d)\n", dev.partname, dev.devname, dev.major, dev.minor);
LOGD("Setup %s: [%s] (%d, %d)\n", dev.partname, dev.devname, dev.major, dev.minor);
dev_t rdev = makedev(dev.major, dev.minor);
mknod(block_dev, S_IFBLK | 0600, rdev);
mknod(blk_info.block_dev, S_IFBLK | 0600, rdev);
return rdev;
}
}
Expand All @@ -90,35 +92,69 @@ static bool is_lnk(const char *name) {
return S_ISLNK(st.st_mode);
}

static bool read_dt_fstab(cmdline *cmd, const char *name) {
char path[128];
int fd;
sprintf(path, "%s/fstab/%s/dev", cmd->dt_dir, name);
if ((fd = open(path, O_RDONLY | O_CLOEXEC)) >= 0) {
read(fd, path, sizeof(path));
close(fd);
path[strcspn(path, "\r\n")] = '\0';
// Some custom treble use different names, so use what we read
char *part = rtrim(strrchr(path, '/') + 1);
sprintf(partname, "%s%s", part, strend(part, cmd->slot) ? cmd->slot : "");
sprintf(path, "%s/fstab/%s/type", cmd->dt_dir, name);
if ((fd = xopen(path, O_RDONLY | O_CLOEXEC)) >= 0) {
read(fd, fstype, 32);
close(fd);
fstype[strcspn(fstype, "\r\n")] = '\0';
return true;
static string rtrim(string &&str) {
// Trim space, newline, and null byte from end of string
while (memchr(" \n\r", str[str.length() - 1], 4))
str.pop_back();
return std::move(str);
}

#define read_info(val) \
if (access(#val, F_OK) == 0) {\
entry.val = rtrim(full_read(#val)); \
}

void BaseInit::read_dt_fstab(map<string_view, fstab_entry> &fstab) {
if (access(cmd->dt_dir, F_OK) != 0)
return;
chdir(cmd->dt_dir);
run_finally cr([]{ chdir("/"); });

if (access("fstab", F_OK) != 0)
return;
chdir("fstab");

auto dir = xopen_dir(".");
for (dirent *dp; (dp = xreaddir(dir.get()));) {
if (dp->d_type != DT_DIR)
continue;
chdir(dp->d_name);
run_finally f([]{ chdir(".."); });

if (access("status", F_OK) == 0) {
auto status = rtrim(full_read("status"));
if (status != "okay" && status != "ok")
continue;
}

fstab_entry entry;

read_info(dev);
read_info(mnt_point) else {
entry.mnt_point = "/";
entry.mnt_point += dp->d_name;
}
read_info(type);
read_info(mnt_flags);
read_info(fsmgr_flags);

fstab.emplace(entry.mnt_point, std::move(entry));
}
return false;
}

#define mount_root(name) \
if (!is_lnk("/" #name) && read_dt_fstab(cmd, #name)) { \
LOGD("Early mount " #name "\n"); \
setup_block(); \
xmkdir("/" #name, 0755); \
xmount(block_dev, "/" #name, fstype, MS_RDONLY, nullptr); \
mount_list.emplace_back("/" #name); \
void BaseInit::dt_early_mount() {
map<string_view, fstab_entry> fstab;
read_dt_fstab(fstab);
for (const auto &[_, entry] : fstab) {
if (is_lnk(entry.mnt_point.data()))
continue;
// Derive partname from dev
sprintf(blk_info.partname, "%s%s", basename(entry.dev.data()), cmd->slot);
setup_block();
xmkdir(entry.mnt_point.data(), 0755);
xmount(blk_info.block_dev, entry.mnt_point.data(), entry.type.data(), MS_RDONLY, nullptr);
mount_list.push_back(entry.mnt_point);
}
}

static void switch_root(const string &path) {
Expand Down Expand Up @@ -152,37 +188,34 @@ static void switch_root(const string &path) {

static void mount_persist(const char *dev_base, const char *mnt_base) {
string mnt_point = mnt_base + "/persist"s;
strcpy(partname, "persist");
xrealpath(dev_base, block_dev);
char *s = block_dev + strlen(block_dev);
strcpy(blk_info.partname, "persist");
xrealpath(dev_base, blk_info.block_dev);
char *s = blk_info.block_dev + strlen(blk_info.block_dev);
strcpy(s, "/persist");
if (setup_block(false) < 0) {
// Fallback to cache
strcpy(partname, "cache");
strcpy(blk_info.partname, "cache");
strcpy(s, "/cache");
if (setup_block(false) < 0) {
// Try NVIDIA's BS
strcpy(partname, "CAC");
strcpy(blk_info.partname, "CAC");
if (setup_block(false) < 0)
return;
}
xsymlink("./cache", mnt_point.data());
mnt_point = mnt_base + "/cache"s;
}
xmkdir(mnt_point.data(), 0755);
xmount(block_dev, mnt_point.data(), "ext4", 0, nullptr);
xmount(blk_info.block_dev, mnt_point.data(), "ext4", 0, nullptr);
}

void RootFSInit::early_mount() {
full_read("/init", self.buf, self.sz);

LOGD("Reverting /init\n");
LOGD("Restoring /init\n");
rename("/.backup/init", "/init");

mount_root(system);
mount_root(vendor);
mount_root(product);
mount_root(odm);
dt_early_mount();

xmkdir("/dev/mnt", 0755);
mount_persist("/dev/block", "/dev/mnt");
Expand All @@ -201,12 +234,12 @@ void SARBase::backup_files() {

void SARBase::mount_system_root() {
LOGD("Early mount system_root\n");
sprintf(partname, "system%s", cmd->slot);
strcpy(block_dev, "/dev/root");
sprintf(blk_info.partname, "system%s", cmd->slot);
strcpy(blk_info.block_dev, "/dev/root");
auto dev = setup_block(false);
if (dev < 0) {
// Try NVIDIA naming scheme
strcpy(partname, "APP");
strcpy(blk_info.partname, "APP");
dev = setup_block(false);
if (dev < 0) {
// We don't really know what to do at this point...
Expand All @@ -230,9 +263,7 @@ void SARInit::early_mount() {
mount_system_root();
switch_root("/system_root");

mount_root(vendor);
mount_root(product);
mount_root(odm);
dt_early_mount();
}

void SARFirstStageInit::early_mount() {
Expand Down Expand Up @@ -262,15 +293,12 @@ void BaseInit::cleanup() {
}

static void patch_socket_name(const char *path) {
char rstr[16];
gen_rand_str(rstr, sizeof(rstr));
char *buf;
size_t size;
mmap_rw(path, buf, size);
for (int i = 0; i < size; ++i) {
if (memcmp(buf + i, MAIN_SOCKET, sizeof(MAIN_SOCKET)) == 0) {
gen_rand_str(buf + i, 16);
i += sizeof(MAIN_SOCKET);
}
}
raw_data_patch(buf, size, { make_pair(MAIN_SOCKET, rstr) });
munmap(buf, size);
}

Expand Down
Loading

0 comments on commit 0c99c4d

Please sign in to comment.