From acc855f711ae7bce20e4fc896c829e135a6801fc Mon Sep 17 00:00:00 2001 From: Tom Marshall Date: Fri, 6 Nov 2015 16:27:01 -0800 Subject: recovery: Handle oemunlock command * Conditionally compile support based on TARGET_HAVE_OEMLOCK. * Use liboemunlock for device specific support. Change-Id: I1cf1fef8e30075b0586bb86625b7df49723974cb --- Android.mk | 7 +++++++ recovery.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- roots.cpp | 4 ++-- roots.h | 2 +- 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. -- cgit v1.1