Skip to content
This repository has been archived by the owner on Dec 30, 2019. It is now read-only.

Commit

Permalink
multirom: Support mounting booted external EXT4/F2FS
Browse files Browse the repository at this point in the history
 * When booting from an EXT4 or F2FS MicroSD / USB Drive,
    the external partition itself is not mountable and
    accessible from the Android userspace for media or data

 * External booted partition is mounted early for /system,
    /data and /cache, therefore e2fsck fails to check,
    and vold avoids mounting the 'corrupted' partition

 * Furthermore on CM/LineageOS based ROMs, external drives
    using EXT4 or F2FS are mounted with an sdcard context,
    which fails due to the superblock mounts mismatching
    the early MultiROM mount of the same partition

 * Work around this limitation from vold and external boots
    by flagging such a boot as an external_mount path,
    remove the fstab entry matching the external MicroSD
    or external USB, and finally mount the partition
    to a new 'external_multirom' folder inside the internal
    media storage under /data/media or /data/media/0

 * Stores external mount paths and filesystem globally
    for later use upon Android mounts preparation

Change-Id: Ifab658ac03a481b40b517a978621f25e09f8622b
Signed-off-by: Adrian DC <radian.dc@gmail.com>
  • Loading branch information
AdrianDC committed Jun 6, 2017
1 parent e4acabe commit 0acfa4c
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 3 deletions.
122 changes: 120 additions & 2 deletions multirom.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ static char kexec_path[64] = { 0 };
static char ntfs_path[64] = { 0 };
static char exfat_path[64] = { 0 };
static char partition_dir[64] = { 0 };
static char external_mount_fs[5] = { 0 };
static char external_mount_part[256] = { 0 };
static char external_mount_path[256] = { 0 };

static volatile int run_usb_refresh = 0;
static pthread_t usb_refresh_thread;
Expand Down Expand Up @@ -1515,6 +1518,24 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom
struct fstab_part *fw_part = NULL;
int res = -1;

// Detect booting from an unmountable external partition
// * Only external partitions have a partition defined
// * Detect ext4 or f2fs as external unmountable because of vold
external_mount_part[0] = 0;
external_mount_path[0] = 0;
if (rom->partition && (strcmp(rom->partition->fs, "ext4") == 0 ||
strcmp(rom->partition->fs, "f2fs") == 0))
{
snprintf(external_mount_part, sizeof(external_mount_part),
"/dev/block/%s", rom->partition->name);
snprintf(external_mount_path, sizeof(external_mount_path),
"/mnt/mrom/%s", rom->partition->name);
snprintf(external_mount_fs, sizeof(external_mount_fs),
"%4s", rom->partition->fs);
ERROR("Booting from external unmountable partition: '%s', %s\n",
external_mount_part, external_mount_fs);
}

sprintf(path, "%s/firmware.img", rom->base_path);
has_fw = (access(path, R_OK) >= 0);

Expand Down Expand Up @@ -1550,7 +1571,7 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom
}
closedir(d);

if(multirom_process_android_fstab(fstab_name, has_fw, &fw_part) != 0)
if (multirom_process_android_fstab(fstab_name, has_fw, &fw_part, s) != 0)
goto exit;

unlink("/cache");
Expand Down Expand Up @@ -1641,7 +1662,8 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom
return res;
}

int multirom_process_android_fstab(char *fstab_name, int has_fw, struct fstab_part **fw_part)
int multirom_process_android_fstab(char *fstab_name, int has_fw,
struct fstab_part **fw_part, struct multirom_status *s)
{
int res = -1;

Expand Down Expand Up @@ -1734,6 +1756,52 @@ int multirom_process_android_fstab(char *fstab_name, int has_fw, struct fstab_pa
mkdir("/dummy_tmpfs", 0644);
}

// Booting from an unmountable external partition
if (external_mount_path[0] != 0)
{
// Access MultiROM fstab as second mount path reference
struct fstab_part* ext_part = NULL;
for (int i = 0; i < s->fstab->count; ++i)
{
if (strcmp(s->fstab->parts[i]->device, external_mount_part) == 0)
{
ext_part = s->fstab->parts[i];
break;
}
}

// Handle external MicroSD boot for voldmanaged removal
if (strstr(external_mount_part, "mmcblk1p1") != NULL ||
ext_part && strstr(ext_part->path, "external_sd") != NULL)
{
ERROR("Searching for voldmanaged 'sdcard1' flag in fstab\n");
for (int i = 0; i < tab->count; ++i)
{
if (strstr(tab->parts[i]->options2, "voldmanaged=sdcard1") != NULL)
{
ERROR("Removing '%s' from fstab to avoid 'voldmanaged'\n",
tab->parts[i]->device);
tab->parts[i]->disabled = 1;
}
}
}
// Handle external USB boot for voldmanaged removal
else if (strstr(external_mount_part, "usb") != NULL ||
ext_part && strstr(ext_part->path, "usb") != NULL)
{
ERROR("Searching for voldmanaged 'usb' flag in fstab\n");
for (int i = 0; i < tab->count; ++i)
{
if (strstr(tab->parts[i]->options2, "voldmanaged=usb") != NULL)
{
ERROR("Removing '%s' from fstab to avoid 'voldmanaged'\n",
tab->parts[i]->device);
tab->parts[i]->disabled = 1;
}
}
}
}

if(fstab_save(tab, fstab_name) == 0)
res = 0;

Expand Down Expand Up @@ -1821,6 +1889,56 @@ int multirom_create_media_link(struct multirom_status *s)
rcadditions_append_trigger(&s->rc, "post-fs-data", " restorecon " LAYOUT_VERSION "\n");
}

// Booting from an unmountable external partition
if (external_mount_path[0] != 0)
{
// Select internal media path for 'external_multirom'
char path_ext[256];
if (stat("/data/media/0", &info) >= 0)
{
snprintf(path_ext, sizeof(path_ext),
"/data/media/0/external_multirom");
}
else
{
snprintf(path_ext, sizeof(path_ext),
"/data/media/external_multirom");
}

INFO("Preparing to mount '%s' to '%s'\n", external_mount_path,
path_ext);

// Create and set accesses to 'external_multirom' on internal media
mkdir(path_ext, 0770);
chmod(path_ext, 0770);

// Bind external partition to internal media 'external_multirom'
if (mount(external_mount_path, path_ext, external_mount_fs, MS_BIND,
"") < 0)
{
ERROR("Failed to bind '%s' (%s) to '%s': %d (%s)\n",
external_mount_path, external_mount_fs, path_ext, errno,
strerror(errno));
external_mount_part[0] = 0;
external_mount_path[0] = 0;
return 0;
}

// Apply internal media owners for 'external_multirom'
unsigned int media_rw_id = decode_uid("media_rw");
if (media_rw_id != -1U)
{
chown(path_ext, (uid_t)media_rw_id, (gid_t)media_rw_id);
}

// Append init restorecon for 'external_multirom' context
char restorecon_ext[64];
snprintf(restorecon_ext, sizeof(restorecon_ext),
" restorecon %s\n", path_ext);
rcadditions_append_trigger(&s->rc, "post-fs-data",
restorecon_ext);
}

return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion multirom.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ void multirom_free_rom(void *rom);
int multirom_init_fb(int rotation);
int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom *rom);
int multirom_create_media_link(struct multirom_status *s);
int multirom_process_android_fstab(char *fstab_name, int has_fw, struct fstab_part **fw_part);
int multirom_process_android_fstab(char *fstab_name, int has_fw, struct fstab_part **fw_part, struct multirom_status *s);
int multirom_get_api_level(const char *path);
int multirom_get_rom_type(struct multirom_rom *rom);
int multirom_get_trampoline_ver(void);
Expand Down

0 comments on commit 0acfa4c

Please sign in to comment.