recovery: Workaround to enable update via sdcard on UFS devices.
The recovery code relies on the recovery.fstab file to locate the
block dev that represents the external sdcard. The dev path is
differrent for UFS and EMMC devices but we can only have a single
entry for both in the fstab.
Since our build is required to support both UFS and EMMC devices
from the same binaries we make this change where recovery when it
sees a request for a update from a sdcard, checks if it is running
on a UFS based target and then does the mount on the correct device.
This is a temporary needed only on builds where we need to support
both UFS and EMMC devices. In practice only one of these will be
present on a device and the recovery.fstab can be updated accordingly.
Change-Id: I28aa99c69c31aa4cfe01bf6854de78b170d75bdb
diff --git a/install.cpp b/install.cpp
index 0860d85..8f327dd 100644
--- a/install.cpp
+++ b/install.cpp
@@ -426,9 +426,11 @@
} else {
LOGE("failed to open last_install: %s\n", strerror(errno));
}
- int result;
+ int result = 0;
std::vector<std::string> log_buffer;
- if (setup_install_mounts() != 0) {
+ if (needs_mount == true)
+ result = setup_install_mounts();
+ if (result != 0) {
LOGE("failed to set up expected mounts for install; aborting\n");
result = INSTALL_ERROR;
} else {
diff --git a/recovery.cpp b/recovery.cpp
index 8a3e759..bc67d94 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -29,6 +29,8 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <sys/mount.h>
+#include <fs_mgr.h>
#include <time.h>
#include <unistd.h>
@@ -60,6 +62,8 @@
#include "ui.h"
#include "screen_ui.h"
+#define UFS_DEV_SDCARD_BLK_PATH "/dev/block/mmcblk0p1"
+
struct selabel_handle *sehandle;
static const struct option OPTIONS[] = {
@@ -986,6 +990,48 @@
ui->ShowText(true);
}
+static int is_ufs_dev()
+{
+ char bootdevice[PROPERTY_VALUE_MAX] = {0};
+ property_get("ro.boot.bootdevice", bootdevice, "N/A");
+ ui->Print("ro.boot.bootdevice is: %s\n",bootdevice);
+ if (strlen(bootdevice) < strlen(".ufshc") + 1)
+ return 0;
+ return (!strncmp(&bootdevice[strlen(bootdevice) - strlen(".ufshc")],
+ ".ufshc",
+ sizeof(".ufshc")));
+}
+
+static int do_sdcard_mount_for_ufs()
+{
+ int rc = 0;
+ ui->Print("Update via sdcard on UFS dev.Mounting card\n");
+ Volume *v = volume_for_path("/sdcard");
+ if (v == NULL) {
+ ui->Print("Unknown volume for /sdcard.Check fstab\n");
+ goto error;
+ }
+ if (strncmp(v->fs_type, "vfat", sizeof("vfat"))) {
+ ui->Print("Unsupported format on the sdcard: %s\n",
+ v->fs_type);
+ goto error;
+ }
+ rc = mount(UFS_DEV_SDCARD_BLK_PATH,
+ v->mount_point,
+ v->fs_type,
+ v->flags,
+ v->fs_options);
+ if (rc) {
+ ui->Print("Failed to mount sdcard : %s\n",
+ strerror(errno));
+ goto error;
+ }
+ ui->Print("Done mounting sdcard\n");
+ return 0;
+error:
+ return -1;
+}
+
// How long (in seconds) we wait for the fuse-provided package file to
// appear, before timing out.
#define SDCARD_INSTALL_TIMEOUT 10
@@ -993,9 +1039,16 @@
static int apply_from_sdcard(Device* device, bool* wipe_cache) {
modified_flash = true;
- if (ensure_path_mounted(SDCARD_ROOT) != 0) {
- ui->Print("\n-- Couldn't mount %s.\n", SDCARD_ROOT);
- return INSTALL_ERROR;
+ if (is_ufs_dev()) {
+ if (do_sdcard_mount_for_ufs() != 0) {
+ ui->Print("\nFailed to mount sdcard\n");
+ return INSTALL_ERROR;
+ }
+ } else {
+ if (ensure_path_mounted(SDCARD_ROOT) != 0) {
+ ui->Print("\n-- Couldn't mount %s.\n", SDCARD_ROOT);
+ return INSTALL_ERROR;
+ }
}
char* path = browse_directory(SDCARD_ROOT, device);
@@ -1397,6 +1450,8 @@
bool shutdown_after = false;
int retry_count = 0;
bool security_update = false;
+ int status = INSTALL_SUCCESS;
+ bool mount_required = true;
int arg;
while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {
@@ -1488,16 +1543,28 @@
else
printf("modified_path allocation failed\n");
}
+ if (!strncmp("/sdcard", update_package, 7)) {
+ //If this is a UFS device lets mount the sdcard ourselves.Depending
+ //on if the device is UFS or EMMC based the path to the sdcard
+ //device changes so we cannot rely on the block dev path from
+ //recovery.fstab
+ if (is_ufs_dev()) {
+ if(do_sdcard_mount_for_ufs() != 0) {
+ status = INSTALL_ERROR;
+ goto error;
+ }
+ mount_required = false;
+ } else {
+ ui->Print("Update via sdcard on EMMC dev. Using path from fstab\n");
+ }
+ }
}
printf("\n");
-
property_list(print_property, NULL);
printf("\n");
ui->Print("Supported API: %d\n", RECOVERY_API_VERSION);
- int status = INSTALL_SUCCESS;
-
if (update_package != NULL) {
// It's not entirely true that we will modify the flash. But we want
// to log the update attempt since update_package is non-NULL.
@@ -1520,7 +1587,7 @@
status = INSTALL_SKIPPED;
} else {
status = install_package(update_package, &should_wipe_cache,
- TEMPORARY_INSTALL_FILE, true, retry_count);
+ TEMPORARY_INSTALL_FILE, mount_required, retry_count);
if (status == INSTALL_SUCCESS && should_wipe_cache) {
wipe_cache(false, device);
}
@@ -1591,7 +1658,8 @@
ui->ShowText(true);
}
}
-
+error:
+ if (is_ro_debuggable()) ui->ShowText(true);
if (!sideload_auto_reboot && (status == INSTALL_ERROR || status == INSTALL_CORRUPT)) {
copy_logs();
ui->SetBackground(RecoveryUI::ERROR);