You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

178 lines
5.7 KiB

/*
* Copyright (C) 2014 MediaTek Inc.
* Modification based on code covered by the mentioned copyright
* and/or permission notice(s).
*/
#include <fs_mgr.h>
#include <cutils/properties.h>
#include <errno.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <sys/mount.h>
#include "roots.h"
#include "common.h"
#include "mt_partition.h"
static int num_volumes = 0;
static Volume* device_volumes = NULL;
static const char* gpt_path_prefix = NULL;
static int parse_options(char* options, Volume* volume) {
char* option;
while ((option = strtok(options, ","))) {
options = NULL;
if (strncmp(option, "length=", 7) == 0) {
volume->length = strtoll(option+7, NULL, 10);
} else {
LOGE("bad option \"%s\"\n", option);
return -1;
}
}
return 0;
}
Volume* mt_volume_for_path(const char* path) {
int i;
for (i = 0; i < num_volumes; ++i) {
Volume* v = device_volumes+i;
int len = strlen(v->mount_point);
if (strncmp(path, v->mount_point, len) == 0 &&
(path[len] == '\0' || path[len] == '/')) {
return v;
}
}
return NULL;
}
char *mt_get_gpt_path(const char *mount_point)
{
char *gpt_path = NULL;
Volume* v = volume_for_mount_point(mount_point);
if (v == NULL) {
v = volume_for_mount_point("/boot");
if (v == NULL) {
LOGE("incorrect fstab information, /boot not find\n");
return NULL;
}
int gpt_path_prefix_len = strlen(v->blk_device) - strlen("/boot") + strlen(mount_point);
gpt_path = (char*) malloc(gpt_path_prefix_len + 1);
strncpy(gpt_path, v->blk_device, strlen(v->blk_device) - strlen("/boot"));
strncpy(gpt_path + strlen(v->blk_device) - strlen("/boot"), mount_point, strlen(mount_point));
gpt_path[gpt_path_prefix_len] = '\0';
} else {
gpt_path = strdup(v->blk_device);
}
return gpt_path;
}
int mt_load_volume_table(struct fstab *fstab)
{
int ret = 0;
ret = set_fs_type_from_property();
if (ret < 0 ) {
LOGE("failed to load fs_type from property\n");
return ret;
}
if (mt_get_phone_type() == FS_TYPE_EMMC) {
#if defined(MTK_GMO_ROM_OPTIMIZE)
ret = fs_mgr_add_entry(fstab, "/sdcard", "vfat", "/dev/block/mmcblk1p1") | fs_mgr_add_entry(fstab, "/sdcard_dev2", "vfat", "/dev/block/mmcblk1");
#else
char *intsd_path = mt_get_gpt_path("/intsd");
ret = fs_mgr_add_entry(fstab, "/sdcard", "vfat", "/dev/block/mmcblk1p1");
if (intsd_path) {
ret |= fs_mgr_add_entry(fstab, "/sdcard_dev2", "vfat", intsd_path);
free(intsd_path);
}
#endif
} else { // for non emmc platform
ret = fs_mgr_add_entry(fstab, "/sdcard", "vfat", "/dev/block/mmcblk0p1") | fs_mgr_add_entry(fstab, "/sdcard_dev2", "vfat", "/dev/block/mmcblk0");
}
if (ret < 0 ) {
LOGE("failed to add /sdcard entry to fstab\n");
return ret;
}
return ret;
}
int mt_mount_sdcard(const char *target_blk_device, Volume* v) {
int result = 0;
result = mount(target_blk_device, v->mount_point, v->fs_type, v->flags, v->fs_options);
if (result != 0) {
//tonykuo 2014-04-11 Try mount mmcblk0 in case mmcblk0p1 failed
if (strstr(target_blk_device, "/dev/block/mmcblk0"))
result = mount("/dev/block/mmcblk0", v->mount_point, v->fs_type, v->flags, v->fs_options);
else if (strstr(target_blk_device, "/dev/block/mmcblk1")) //Try mount mmcblk1 in case mmcblk1p1 failed
result = mount("/dev/block/mmcblk1", v->mount_point, v->fs_type, v->flags, v->fs_options);
}
return result;
}
int mt_ensure_path_mounted(Volume* v) {
int result = -1;
//wschen 2013-05-03 workaround for slowly SD
if (strstr(v->mount_point, "/sdcard") && (strstr(v->blk_device, "/dev/block/mmcblk1") || strstr(v->blk_device, "/dev/block/mmcblk0"))) {
int retry = 0;
for (; retry <= 3; retry++) {
result = mt_mount_sdcard(v->blk_device, v);
if (result == 0)
return result;
else
sleep(1);
}
printf("Slowly SD retry failed (%s)\n", v->blk_device);
}
// mount sdcard fail, try to mount another blk_dev
if (!strcmp(v->mount_point, "/sdcard")) {
Volume* v_dev2 = volume_for_mount_point("/sdcard_dev2");
if (v_dev2) {
LOGE("failed to mount %s (%s); trying %s\n", v->blk_device, strerror(errno), v_dev2->blk_device);
result = mt_mount_sdcard(v_dev2->blk_device, v);
}
}
return result;
}
void mt_ensure_dev_ready(const char *mount_point) {
int count=0;
Volume* v = volume_for_mount_point(mount_point);
if (v) {
while ((count++ < 5) && (access(v->blk_device, R_OK) != 0)) {
printf("no %s entry %s, count = %d\n", mount_point, v->blk_device, count);
sleep(1);
}
} else {
printf("Error: Retry fail %s partition not found\n",mount_point);
}
}
void mt_fstab_translation_NAND(struct fstab *fstab) {
int i;
char *dev_name = NULL;
Volume* v = volume_for_mount_point("/misc");
if (v && (!strcmp(v->fs_type, "emmc")))
return;
printf("storage is NAND, need to translate fstab\n");
for (i = 0; i < fstab->num_entries; ++i) {
Volume* v = &fstab->recs[i];
if (!strcmp(v->fs_type, "ubifs") || !strcmp(v->fs_type, "yaffs2") || !strcmp(v->fs_type, "mtd")) {
if (v->blk_device) {
dev_name = strrchr(v->blk_device, '@');
dev_name = strdup(dev_name ? dev_name + 1 : v->blk_device);
free(v->blk_device);
v->blk_device = dev_name;
}
else {
printf("mt_fstab_translation_NAND fail\n");
}
}
}
}