aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Marshall <tdm@cyngn.com>2015-11-06 16:27:01 -0800
committerTom Marshall <tdm@cyngn.com>2015-11-25 15:34:35 -0800
commitacc855f711ae7bce20e4fc896c829e135a6801fc (patch)
treea7be8c1fc394571765cda5e8b27c12c92ec1cc7d
parente1ba5bc721daf65598feb2b5c46d1c06fac63ec4 (diff)
downloadbootable_recovery-acc855f711ae7bce20e4fc896c829e135a6801fc.zip
bootable_recovery-acc855f711ae7bce20e4fc896c829e135a6801fc.tar.gz
bootable_recovery-acc855f711ae7bce20e4fc896c829e135a6801fc.tar.bz2
recovery: Handle oemunlock command
* Conditionally compile support based on TARGET_HAVE_OEMLOCK. * Use liboemunlock for device specific support. Change-Id: I1cf1fef8e30075b0586bb86625b7df49723974cb
-rw-r--r--Android.mk7
-rw-r--r--recovery.cpp60
-rw-r--r--roots.cpp4
-rw-r--r--roots.h2
4 files changed, 66 insertions, 7 deletions
diff --git a/Android.mk b/Android.mk
index c5fdbd1..55adbaa 100644
--- a/Android.mk
+++ b/Android.mk
@@ -102,6 +102,13 @@ LOCAL_STATIC_LIBRARIES := \
libext2_blkid \
libext2_uuid
+# OEMLOCK support requires a device specific liboemlock be supplied.
+# See comments in recovery.cpp for the API.
+ifeq ($(TARGET_HAVE_OEMLOCK), true)
+ LOCAL_CFLAGS += -DHAVE_OEMLOCK
+ LOCAL_STATIC_LIBRARIES += liboemlock
+endif
+
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
ifeq ($(TARGET_USE_MDTP), true)
diff --git a/recovery.cpp b/recovery.cpp
index d3dc398..3a1fd61 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -61,6 +61,39 @@ extern "C" {
struct selabel_handle *sehandle;
+#ifdef HAVE_OEMLOCK
+
+/*
+ * liboemlock must supply the following C symbols:
+ *
+ * - int oemlock_get()
+ *
+ * Returns the current state of the OEM lock, if available.
+ * -1: Not available and/or error
+ * 0: Unlocked
+ * 1: Locked
+ *
+ * - int oemlock_set(int lock)
+ *
+ * Sets the state of the OEM lock. The "lock" parameter will be set
+ * to 0 for unlock and 1 for lock.
+ *
+ * Returns 0 on success, -1 on error
+ */
+extern "C" {
+int oemlock_get();
+int oemlock_set(int lock);
+}
+
+enum OemLockOp {
+ OEM_LOCK_NONE,
+ OEM_LOCK_UNLOCK
+};
+
+static OemLockOp oem_lock = OEM_LOCK_NONE;
+
+#endif
+
static const struct option OPTIONS[] = {
{ "send_intent", required_argument, NULL, 'i' },
{ "update_package", required_argument, NULL, 'u' },
@@ -302,6 +335,14 @@ get_args(int *argc, char ***argv) {
(*argv)[0] = strdup(arg);
for (*argc = 1; *argc < MAX_ARGS; ++*argc) {
if ((arg = strtok(NULL, "\n")) == NULL) break;
+ // Arguments that may only be passed in BCB
+#ifdef HAVE_OEMLOCK
+ if (strcmp(arg, "--oemunlock") == 0) {
+ oem_lock = OEM_LOCK_UNLOCK;
+ --*argc;
+ continue;
+ }
+#endif
(*argv)[*argc] = strdup(arg);
}
LOGI("Got arguments from boot message\n");
@@ -510,7 +551,7 @@ typedef struct _saved_log_file {
struct _saved_log_file* next;
} saved_log_file;
-static bool erase_volume(const char* volume) {
+static bool erase_volume(const char* volume, bool force = false) {
bool is_cache = (strcmp(volume, CACHE_ROOT) == 0);
ui->SetBackground(RecoveryUI::ERASING);
@@ -518,7 +559,7 @@ static bool erase_volume(const char* volume) {
saved_log_file* head = NULL;
- if (is_cache) {
+ if (!force && is_cache) {
// If we're reformatting /cache, we load any past logs
// (i.e. "/cache/recovery/last_*") and the current log
// ("/cache/recovery/log") into memory, so we can restore them after
@@ -568,9 +609,9 @@ static bool erase_volume(const char* volume) {
if (volume[0] == '/') {
ensure_path_unmounted(volume);
}
- int result = format_volume(volume);
+ int result = format_volume(volume, force);
- if (is_cache) {
+ if (!force && is_cache) {
while (head) {
FILE* f = fopen_path(head->name, "wb");
if (f) {
@@ -1343,6 +1384,17 @@ main(int argc, char **argv) {
int status = INSTALL_SUCCESS;
+#ifdef HAVE_OEMLOCK
+ if (oem_lock == OEM_LOCK_UNLOCK) {
+ if (device->WipeData()) status = INSTALL_ERROR;
+ if (erase_volume("/data", true)) status = INSTALL_ERROR;
+ if (wipe_cache && erase_volume("/cache", true)) status = INSTALL_ERROR;
+ if (status != INSTALL_SUCCESS) ui->Print("Data wipe failed.\n");
+ if (oemlock_set(0)) status = INSTALL_ERROR;
+ // Force reboot regardless of actual status
+ status = INSTALL_SUCCESS;
+ } else
+#endif
if (update_package != NULL) {
status = install_package(update_package, &should_wipe_cache, TEMPORARY_INSTALL_FILE, true);
if (status == INSTALL_SUCCESS && should_wipe_cache) {
diff --git a/roots.cpp b/roots.cpp
index fda8f61..d27a2dd 100644
--- a/roots.cpp
+++ b/roots.cpp
@@ -348,7 +348,7 @@ static int rmtree_except(const char* path, const char* except)
return rc;
}
-int format_volume(const char* volume) {
+int format_volume(const char* volume, bool force) {
if (strcmp(volume, "media") == 0) {
if (!vdc->isEmulatedStorage()) {
return 0;
@@ -378,7 +378,7 @@ int format_volume(const char* volume) {
return -1;
}
- if (strcmp(volume, "/data") == 0 && vdc->isEmulatedStorage()) {
+ if (!force && strcmp(volume, "/data") == 0 && vdc->isEmulatedStorage()) {
if (ensure_path_mounted("/data") == 0) {
// Preserve .layout_version to avoid "nesting bug"
LOGI("Preserving layout version\n");
diff --git a/roots.h b/roots.h
index 9b369c0..addb142 100644
--- a/roots.h
+++ b/roots.h
@@ -42,7 +42,7 @@ int ensure_path_unmounted(const char* path, bool detach=false);
// Reformat the given volume (must be the mount point only, eg
// "/cache"), no paths permitted. Attempts to unmount the volume if
// it is mounted.
-int format_volume(const char* volume);
+int format_volume(const char* volume, bool force = false);
// Ensure that all and only the volumes that packages expect to find
// mounted (/tmp and /cache) are mounted. Returns 0 on success.