Erase PST partition if its marked to be erased.

We need to wipe the challenges on this partition
if OEM unlock is enabled, as this is a signal that
the user has opted out of factory reset protection.

go/factory-reset

Bug: 16633064
Change-Id: Icb8f1433bf99ca57813f5b72d5a3dd15fa94a263
diff --git a/recovery.cpp b/recovery.cpp
index d2d85e7..f78d6e4 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -659,6 +659,7 @@
     device->WipeData();
     erase_volume("/data");
     erase_volume("/cache");
+    erase_persistent_partition();
     ui->Print("Data wipe complete.\n");
 }
 
@@ -959,6 +960,7 @@
         if (device->WipeData()) status = INSTALL_ERROR;
         if (erase_volume("/data")) status = INSTALL_ERROR;
         if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR;
+        if (erase_persistent_partition() == -1 ) status = INSTALL_ERROR;
         if (status != INSTALL_SUCCESS) ui->Print("Data wipe failed.\n");
     } else if (wipe_cache) {
         if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR;
diff --git a/roots.cpp b/roots.cpp
index 8f99019..61798f4 100644
--- a/roots.cpp
+++ b/roots.cpp
@@ -39,6 +39,8 @@
 
 extern struct selabel_handle *sehandle;
 
+static const char* PERSISTENT_PATH = "/persistent";
+
 void load_volume_table()
 {
     int i;
@@ -264,6 +266,41 @@
     return -1;
 }
 
+int erase_persistent_partition() {
+    Volume *v = volume_for_path(PERSISTENT_PATH);
+    if (v == NULL) {
+        // most devices won't have /persistent, so this is not an error.
+        return 0;
+    }
+
+    int fd = open(v->blk_device, O_RDWR);
+    uint64_t size = get_file_size(fd);
+    if (size == 0) {
+        LOGE("failed to stat size of /persistent\n");
+        close(fd);
+        return -1;
+    }
+
+    char oem_unlock_enabled;
+    lseek(fd, size - 1, SEEK_SET);
+    read(fd, &oem_unlock_enabled, 1);
+
+    if (oem_unlock_enabled) {
+        if (wipe_block_device(fd, size)) {
+           LOGE("error wiping /persistent: %s\n", strerror(errno));
+           close(fd);
+           return -1;
+        }
+
+        lseek(fd, size - 1, SEEK_SET);
+        write(fd, &oem_unlock_enabled, 1);
+    }
+
+    close(fd);
+
+    return (int) oem_unlock_enabled;
+}
+
 int setup_install_mounts() {
     if (fstab == NULL) {
         LOGE("can't set up install mounts: no fstab loaded\n");
diff --git a/roots.h b/roots.h
index 230d9de..b62a5b1 100644
--- a/roots.h
+++ b/roots.h
@@ -46,6 +46,11 @@
 // mounted (/tmp and /cache) are mounted.  Returns 0 on success.
 int setup_install_mounts();
 
+// Conditionally wipes the /persistent partition if it's marked
+// to wipe. Returns -1 on failure, 1 if the partition was wiped
+// and 0 if the partition was not wiped.
+int erase_persistent_partition();
+
 #ifdef __cplusplus
 }
 #endif