summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk16
-rw-r--r--BasePartition.cpp28
-rw-r--r--crypto/ext4crypt/Android.mk2
-rw-r--r--crypto/ext4crypt/Ext4Crypt.cpp3
-rw-r--r--crypto/ext4crypt/Ext4CryptPie.cpp5
-rw-r--r--crypto/ext4crypt/MetadataCrypt.cpp271
-rw-r--r--crypto/ext4crypt/MetadataCrypt.h25
-rw-r--r--crypto/vold_decrypt/Android.bp--skip_soong--15
-rw-r--r--crypto/vold_decrypt/Android.mk40
-rw-r--r--crypto/vold_decrypt/init.recovery.vold_decrypt.servicemanager.rc8
-rw-r--r--crypto/vold_decrypt/vdc_pie.cpp106
-rw-r--r--crypto/vold_decrypt/vold_decrypt.cpp243
-rw-r--r--crypto/vold_decrypt/vold_decrypt.h1
-rw-r--r--data.cpp16
-rw-r--r--etc/Android.mk15
-rw-r--r--etc/init.rc1
-rwxr-xr-xetc/init.recovery.mksh.rc2
-rw-r--r--etc/init.recovery.service22.rc6
-rw-r--r--gui/action.cpp20
-rw-r--r--gui/theme/landscape_hdpi/ui.xml5
-rw-r--r--gui/theme/landscape_mdpi/ui.xml5
-rw-r--r--gui/theme/portrait_hdpi/ui.xml5
-rw-r--r--gui/theme/portrait_mdpi/ui.xml5
-rw-r--r--minui/events.cpp1
-rw-r--r--minui/graphics_overlay.cpp6
-rw-r--r--minuitwrp/Android.mk4
-rw-r--r--minuitwrp/events.cpp36
-rw-r--r--minuitwrp/graphics.cpp4
-rw-r--r--minuitwrp/graphics_adf.cpp1
-rw-r--r--minuitwrp/graphics_drm.cpp4
-rw-r--r--minuitwrp/graphics_fbdev.cpp6
-rw-r--r--minuitwrp/graphics_overlay.cpp8
-rw-r--r--minuitwrp/graphics_utils.cpp5
-rw-r--r--openrecoveryscript.cpp10
-rw-r--r--partition.cpp213
-rw-r--r--partitionmanager.cpp39
-rw-r--r--partitions.hpp20
-rw-r--r--prebuilt/Android.mk69
-rwxr-xr-xprebuilt/mkshrc_twrp21
-rwxr-xr-xprebuilt/vdc_pie-armbin0 -> 46588 bytes
-rwxr-xr-xprebuilt/vdc_pie-arm64bin0 -> 69824 bytes
-rw-r--r--toybox/Android.mk2
-rw-r--r--twrp-functions.cpp22
-rw-r--r--twrp.cpp2
-rw-r--r--twrpAdbBuFifo.cpp2
-rw-r--r--updater/install.cpp28
46 files changed, 1124 insertions, 222 deletions
diff --git a/Android.mk b/Android.mk
index cacd783bb..95c190ea8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -15,7 +15,7 @@
LOCAL_PATH := $(call my-dir)
commands_TWRP_local_path := $(LOCAL_PATH)
-ifdef project-path-for
+ifneq ($(project-path-for),)
ifeq ($(LOCAL_PATH),$(call project-path-for,recovery))
PROJECT_PATH_AGREES := true
BOARD_SEPOLICY_DIRS += $(call project-path-for,recovery)/sepolicy
@@ -196,6 +196,11 @@ LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
#else
# LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UI_LIB)
#endif
+ifeq ($(TARGET_RECOVERY_TWRP_LIB),)
+ LOCAL_SRC_FILES += BasePartition.cpp
+else
+ LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_TWRP_LIB)
+endif
LOCAL_C_INCLUDES += system/extras/ext4_utils
@@ -302,6 +307,9 @@ ifeq ($(TW_INCLUDE_CRYPTO), true)
TW_INCLUDE_CRYPTO_FBE := true
LOCAL_CFLAGS += -DTW_INCLUDE_FBE
LOCAL_SHARED_LIBRARIES += libe4crypt
+ ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 28; echo $$?),0)
+ LOCAL_CFLAGS += -DTW_INCLUDE_FBE_METADATA_DECRYPT
+ endif
endif
ifneq ($(TW_CRYPTO_USE_SYSTEM_VOLD),)
ifneq ($(TW_CRYPTO_USE_SYSTEM_VOLD),false)
@@ -315,6 +323,9 @@ WITH_CRYPTO_UTILS := \
ifeq ($(TW_USE_MODEL_HARDWARE_ID_FOR_DEVICE_ID), true)
LOCAL_CFLAGS += -DTW_USE_MODEL_HARDWARE_ID_FOR_DEVICE_ID
endif
+ifeq ($(TW_USE_SERIALNO_PROPERTY_FOR_DEVICE_ID), true)
+ LOCAL_CFLAGS += -DTW_USE_SERIALNO_PROPERTY_FOR_DEVICE_ID
+endif
ifneq ($(TW_BRIGHTNESS_PATH),)
LOCAL_CFLAGS += -DTW_BRIGHTNESS_PATH=$(TW_BRIGHTNESS_PATH)
endif
@@ -479,6 +490,9 @@ ifeq ($(shell test $(CM_PLATFORM_SDK_VERSION) -ge 3; echo $$?),0)
fsck.f2fs \
mkfs.f2fs
endif
+ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 28; echo $$?),0)
+ LOCAL_REQUIRED_MODULES += sload.f2fs
+endif
endif
ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 25; echo $$?),0)
diff --git a/BasePartition.cpp b/BasePartition.cpp
new file mode 100644
index 000000000..3b34d75c2
--- /dev/null
+++ b/BasePartition.cpp
@@ -0,0 +1,28 @@
+/*
+ Copyright 2018 TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include "partitions.hpp"
+
+// On devices that need it, this is supposed to be overridden using
+// TARGET_RECOVERY_TWRP_LIB to allow device-specific pre and post
+// wipe encryption calls.
+
+BasePartition* make_partition() {
+ return new BasePartition();
+}
diff --git a/crypto/ext4crypt/Android.mk b/crypto/ext4crypt/Android.mk
index e589903d9..8e77cdf30 100644
--- a/crypto/ext4crypt/Android.mk
+++ b/crypto/ext4crypt/Android.mk
@@ -21,7 +21,7 @@ ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26; echo $$?),0)
ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 28; echo $$?),0)
#9.0 rules
LOCAL_CFLAGS += -DUSE_KEYSTORAGE_4 -Wno-unused-variable -Wno-sign-compare -Wno-unused-parameter -Wno-comment
- LOCAL_SRC_FILES += Ext4CryptPie.cpp Keymaster4.cpp KeyStorage4.cpp KeyUtil.cpp
+ LOCAL_SRC_FILES += Ext4CryptPie.cpp Keymaster4.cpp KeyStorage4.cpp KeyUtil.cpp MetadataCrypt.cpp KeyBuffer.cpp
LOCAL_SHARED_LIBRARIES += android.hardware.keymaster@4.0 libkeymaster4support
LOCAL_SHARED_LIBRARIES += android.hardware.gatekeeper@1.0 libkeystore_parcelables libkeystore_aidl
LOCAL_CFLAGS += -DHAVE_SYNTH_PWD_SUPPORT
diff --git a/crypto/ext4crypt/Ext4Crypt.cpp b/crypto/ext4crypt/Ext4Crypt.cpp
index 15d7d8f32..c9e71fd9b 100644
--- a/crypto/ext4crypt/Ext4Crypt.cpp
+++ b/crypto/ext4crypt/Ext4Crypt.cpp
@@ -317,9 +317,8 @@ bool lookup_key_ref(const std::map<userid_t, std::string>& key_map, userid_t use
}
static bool ensure_policy(const std::string& raw_ref __unused, const std::string& path) {
- LOG(INFO) << "ensure_policy '" << path << "'\n";
return true;
- return access(path.c_str(), F_OK) == 0; // ensure policy will set a policy if one is not set on an empty folder - we don't want to do this in recovery
+ // ensure policy will set a policy if one is not set on an empty folder - we don't want to do this in recovery
/*if (e4crypt_policy_ensure(path.c_str(), raw_ref.data(), raw_ref.size()) != 0) {
LOG(ERROR) << "Failed to set policy on: " << path << "\n";
return false;
diff --git a/crypto/ext4crypt/Ext4CryptPie.cpp b/crypto/ext4crypt/Ext4CryptPie.cpp
index 615229ea9..d6ea53156 100644
--- a/crypto/ext4crypt/Ext4CryptPie.cpp
+++ b/crypto/ext4crypt/Ext4CryptPie.cpp
@@ -295,9 +295,10 @@ static void get_data_file_encryption_modes(PolicyKeyRef* key_ref) {
}
static bool ensure_policy(const PolicyKeyRef& key_ref, const std::string& path) {
- return e4crypt_policy_ensure(path.c_str(), key_ref.key_raw_ref.data(),
+ return true;
+ /*return e4crypt_policy_ensure(path.c_str(), key_ref.key_raw_ref.data(),
key_ref.key_raw_ref.size(), key_ref.contents_mode.c_str(),
- key_ref.filenames_mode.c_str()) == 0;
+ key_ref.filenames_mode.c_str()) == 0;*/
}
static bool is_numeric(const char* name) {
diff --git a/crypto/ext4crypt/MetadataCrypt.cpp b/crypto/ext4crypt/MetadataCrypt.cpp
new file mode 100644
index 000000000..b195fa09e
--- /dev/null
+++ b/crypto/ext4crypt/MetadataCrypt.cpp
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "KeyBuffer.h"
+#include "MetadataCrypt.h"
+
+#include <string>
+#include <thread>
+#include <vector>
+#include <algorithm>
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <linux/dm-ioctl.h>
+
+//#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/unique_fd.h>
+#include <cutils/fs.h>
+//#include <fs_mgr.h>
+
+//#include "EncryptInplace.h"
+#include "KeyStorage4.h"
+#include "KeyUtil.h"
+//#include "secontext.h"
+#include "Utils.h"
+//#include "VoldUtil.h"
+
+#include <iostream>
+#define LOG(x) std::cout
+#define PLOG(x) std::cout
+#include <linux/fs.h>
+
+#define DM_CRYPT_BUF_SIZE 4096
+#define TABLE_LOAD_RETRIES 10
+#define DEFAULT_KEY_TARGET_TYPE "default-key"
+
+using android::vold::KeyBuffer;
+
+static const std::string kDmNameUserdata = "userdata";
+
+void get_blkdev_size(int fd, unsigned long* nr_sec) {
+ if ((ioctl(fd, BLKGETSIZE, nr_sec)) == -1) {
+ *nr_sec = 0;
+ }
+}
+
+static const char* kLookup = "0123456789abcdef";
+
+android::status_t StrToHex(const KeyBuffer& str, KeyBuffer& hex) {
+ hex.clear();
+ for (size_t i = 0; i < str.size(); i++) {
+ hex.push_back(kLookup[(str.data()[i] & 0xF0) >> 4]);
+ hex.push_back(kLookup[str.data()[i] & 0x0F]);
+ }
+ return android::OK;
+}
+
+/*static bool mount_via_fs_mgr(const char* mount_point, const char* blk_device) {
+ // fs_mgr_do_mount runs fsck. Use setexeccon to run trusted
+ // partitions in the fsck domain.
+ if (setexeccon(secontextFsck())) {
+ PLOG(ERROR) << "Failed to setexeccon";
+ return false;
+ }
+ auto mount_rc = fs_mgr_do_mount(fstab_default, const_cast<char*>(mount_point),
+ const_cast<char*>(blk_device), nullptr);
+ if (setexeccon(nullptr)) {
+ PLOG(ERROR) << "Failed to clear setexeccon";
+ return false;
+ }
+ if (mount_rc != 0) {
+ LOG(ERROR) << "fs_mgr_do_mount failed with rc " << mount_rc;
+ return false;
+ }
+ LOG(DEBUG) << "Mounted " << mount_point;
+ return true;
+}*/
+
+static bool read_key(const std::string& key_dir, bool create_if_absent, KeyBuffer* key) {
+ /*if (!data_rec->key_dir) {
+ LOG(ERROR) << "Failed to get key_dir";
+ return false;
+ }
+ std::string key_dir = data_rec->key_dir;*/
+ auto dir = key_dir + "/key";
+ LOG(DEBUG) << "key_dir/key: " << dir << "\n";
+ /*if (fs_mkdirs(dir.c_str(), 0700)) {
+ PLOG(ERROR) << "Creating directories: " << dir;
+ return false;
+ }*/
+ auto temp = key_dir + "/tmp";
+ if (!android::vold::retrieveKey(create_if_absent, dir, temp, key)) return false;
+ return true;
+}
+
+static KeyBuffer default_key_params(const std::string& real_blkdev, const KeyBuffer& key) {
+ KeyBuffer hex_key;
+ if (/*android::vold::*/StrToHex(key, hex_key) != android::OK) {
+ LOG(ERROR) << "Failed to turn key to hex\n";
+ return KeyBuffer();
+ }
+ auto res = KeyBuffer() + "AES-256-XTS " + hex_key + " " + real_blkdev.c_str() + " 0";
+ return res;
+}
+
+static bool get_number_of_sectors(const std::string& real_blkdev, uint64_t *nr_sec) {
+ android::base::unique_fd dev_fd(TEMP_FAILURE_RETRY(open(
+ real_blkdev.c_str(), O_RDONLY | O_CLOEXEC, 0)));
+ if (dev_fd == -1) {
+ PLOG(ERROR) << "Unable to open " << real_blkdev << " to measure size\n";
+ return false;
+ }
+ unsigned long res;
+ // TODO: should use BLKGETSIZE64
+ get_blkdev_size(dev_fd.get(), &res);
+ if (res == 0) {
+ PLOG(ERROR) << "Unable to measure size of " << real_blkdev << "\n";
+ return false;
+ }
+ *nr_sec = res;
+ return true;
+}
+
+static struct dm_ioctl* dm_ioctl_init(char *buffer, size_t buffer_size,
+ const std::string& dm_name) {
+ if (buffer_size < sizeof(dm_ioctl)) {
+ LOG(ERROR) << "dm_ioctl buffer too small\n";
+ return nullptr;
+ }
+
+ memset(buffer, 0, buffer_size);
+ struct dm_ioctl* io = (struct dm_ioctl*) buffer;
+ io->data_size = buffer_size;
+ io->data_start = sizeof(struct dm_ioctl);
+ io->version[0] = 4;
+ io->version[1] = 0;
+ io->version[2] = 0;
+ io->flags = 0;
+ dm_name.copy(io->name, sizeof(io->name));
+ return io;
+}
+
+static bool create_crypto_blk_dev(const std::string& dm_name, uint64_t nr_sec,
+ const std::string& target_type, const KeyBuffer& crypt_params,
+ std::string* crypto_blkdev) {
+ PLOG(INFO) << "starting create_crypto_blk_dev\n";
+ android::base::unique_fd dm_fd(TEMP_FAILURE_RETRY(open(
+ "/dev/device-mapper", O_RDWR | O_CLOEXEC, 0)));
+ if (dm_fd == -1) {
+ PLOG(ERROR) << "Cannot open device-mapper\n";
+ return false;
+ }
+ alignas(struct dm_ioctl) char buffer[DM_CRYPT_BUF_SIZE];
+ auto io = dm_ioctl_init(buffer, sizeof(buffer), dm_name);
+ if (!io || ioctl(dm_fd.get(), DM_DEV_CREATE, io) != 0) {
+ PLOG(ERROR) << "Cannot create dm-crypt device " << dm_name << "\n";
+ return false;
+ }
+
+ // Get the device status, in particular, the name of its device file
+ io = dm_ioctl_init(buffer, sizeof(buffer), dm_name);
+ if (ioctl(dm_fd.get(), DM_DEV_STATUS, io) != 0) {
+ PLOG(ERROR) << "Cannot retrieve dm-crypt device status " << dm_name << "\n";
+ return false;
+ }
+ *crypto_blkdev = std::string() + "/dev/block/dm-" + std::to_string(
+ (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00));
+
+ io = dm_ioctl_init(buffer, sizeof(buffer), dm_name);
+ size_t paramix = io->data_start + sizeof(struct dm_target_spec);
+ size_t nullix = paramix + crypt_params.size();
+ size_t endix = (nullix + 1 + 7) & 8; // Add room for \0 and align to 8 byte boundary
+
+ if (endix > sizeof(buffer)) {
+ LOG(ERROR) << "crypt_params too big for DM_CRYPT_BUF_SIZE\n";
+ return false;
+ }
+
+ io->target_count = 1;
+ auto tgt = (struct dm_target_spec *) (buffer + io->data_start);
+ tgt->status = 0;
+ tgt->sector_start = 0;
+ tgt->length = nr_sec;
+ target_type.copy(tgt->target_type, sizeof(tgt->target_type));
+ memcpy(buffer + paramix, crypt_params.data(),
+ std::min(crypt_params.size(), sizeof(buffer) - paramix));
+ buffer[nullix] = '\0';
+ tgt->next = endix;
+
+ for (int i = 0; ; i++) {
+ if (ioctl(dm_fd.get(), DM_TABLE_LOAD, io) == 0) {
+ break;
+ }
+ if (i+1 >= TABLE_LOAD_RETRIES) {
+ PLOG(ERROR) << "DM_TABLE_LOAD ioctl failed\n";
+ return false;
+ }
+ PLOG(INFO) << "DM_TABLE_LOAD ioctl failed, retrying\n";
+ usleep(500000);
+ }
+
+ // Resume this device to activate it
+ io = dm_ioctl_init(buffer, sizeof(buffer), dm_name);
+ if (ioctl(dm_fd.get(), DM_DEV_SUSPEND, io)) {
+ PLOG(ERROR) << "Cannot resume dm-crypt device " << dm_name << "\n";
+ return false;
+ }
+ return true;
+}
+
+bool e4crypt_mount_metadata_encrypted(const std::string& mount_point, bool needs_encrypt, const std::string& key_dir, const std::string& blk_device, std::string* crypto_blkdev) {
+ LOG(DEBUG) << "e4crypt_mount_metadata_encrypted: " << mount_point << " " << needs_encrypt << "\n";
+ /*auto encrypted_state = android::base::GetProperty("ro.crypto.state", "");
+ if (encrypted_state != "") {
+ LOG(DEBUG) << "e4crypt_enable_crypto got unexpected starting state: " << encrypted_state;
+ return false;
+ }
+ auto data_rec = fs_mgr_get_entry_for_mount_point(fstab_default, mount_point);
+ if (!data_rec) {
+ LOG(ERROR) << "Failed to get data_rec";
+ return false;
+ }*/
+ KeyBuffer key;
+ if (!read_key(key_dir, needs_encrypt, &key)) return false;
+ uint64_t nr_sec;
+ if (!get_number_of_sectors(blk_device, &nr_sec)) return false;
+ //std::string crypto_blkdev;
+ if (!create_crypto_blk_dev(kDmNameUserdata, nr_sec, DEFAULT_KEY_TARGET_TYPE,
+ default_key_params(blk_device, key), /*&*/crypto_blkdev))
+ return false;
+ // FIXME handle the corrupt case
+ /*if (needs_encrypt) {
+ LOG(INFO) << "Beginning inplace encryption, nr_sec: " << nr_sec;
+ off64_t size_already_done = 0;
+ auto rc =
+ cryptfs_enable_inplace(const_cast<char*>(crypto_blkdev.c_str()), data_rec->blk_device,
+ nr_sec, &size_already_done, nr_sec, 0, false);
+ if (rc != 0) {
+ LOG(ERROR) << "Inplace crypto failed with code: " << rc;
+ return false;
+ }
+ if (static_cast<uint64_t>(size_already_done) != nr_sec) {
+ LOG(ERROR) << "Inplace crypto only got up to sector: " << size_already_done;
+ return false;
+ }
+ LOG(INFO) << "Inplace encryption complete";
+ }
+
+ LOG(DEBUG) << "Mounting metadata-encrypted filesystem:" << mount_point;
+ mount_via_fs_mgr(data_rec->mount_point, crypto_blkdev.c_str());*/
+ LOG(DEBUG) << "crypto block device '" << *crypto_blkdev << "\n";
+ return true;
+}
diff --git a/crypto/ext4crypt/MetadataCrypt.h b/crypto/ext4crypt/MetadataCrypt.h
new file mode 100644
index 000000000..69addf318
--- /dev/null
+++ b/crypto/ext4crypt/MetadataCrypt.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _METADATA_CRYPT_H
+#define _METADATA_CRYPT_H
+
+#include <string>
+__BEGIN_DECLS
+bool e4crypt_mount_metadata_encrypted(const std::string& mount_point, bool needs_encrypt, const std::string& key_dir, const std::string& blk_device, std::string* crypto_blkdev);
+__END_DECLS
+
+#endif
diff --git a/crypto/vold_decrypt/Android.bp--skip_soong-- b/crypto/vold_decrypt/Android.bp--skip_soong--
new file mode 100644
index 000000000..f16942df2
--- /dev/null
+++ b/crypto/vold_decrypt/Android.bp--skip_soong--
@@ -0,0 +1,15 @@
+cc_binary {
+ name: "vdc_pie",
+ defaults: ["vold_default_flags"],
+
+ srcs: ["vdc_pie.cpp"],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "libutils",
+ ],
+ static_libs: [
+ "libvold_binder",
+ ],
+}
diff --git a/crypto/vold_decrypt/Android.mk b/crypto/vold_decrypt/Android.mk
index 19c2963c0..860e61f20 100644
--- a/crypto/vold_decrypt/Android.mk
+++ b/crypto/vold_decrypt/Android.mk
@@ -27,6 +27,12 @@ ifeq ($(TW_INCLUDE_CRYPTO), true)
services := $(TW_CRYPTO_USE_SYSTEM_VOLD)
endif
+ # Parse TW_CRYPTO_SYSTEM_VOLD_MOUNT
+ ifneq ($(TW_CRYPTO_SYSTEM_VOLD_MOUNT),)
+ # Per device additional partitions to mount
+ partitions := $(TW_CRYPTO_SYSTEM_VOLD_MOUNT)
+ endif
+
# List of .rc files for each additional service
rc_files := $(foreach item,$(services),init.recovery.vold_decrypt.$(item).rc)
@@ -86,6 +92,10 @@ ifeq ($(TW_INCLUDE_CRYPTO), true)
endif
endif
+ ifneq ($(partitions),)
+ LOCAL_CFLAGS += -DTW_CRYPTO_SYSTEM_VOLD_MOUNT='"$(partitions)"'
+ endif
+
ifeq ($(TW_CRYPTO_SYSTEM_VOLD_DEBUG),true)
# Enabling strace will expose the password in the strace logs!!
LOCAL_CFLAGS += -DTW_CRYPTO_SYSTEM_VOLD_DEBUG
@@ -101,5 +111,35 @@ ifeq ($(TW_INCLUDE_CRYPTO), true)
LOCAL_SHARED_LIBRARIES := libcutils
include $(BUILD_STATIC_LIBRARY)
+ ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 28; echo $$?),0)
+ include $(CLEAR_VARS)
+ LOCAL_MODULE := vdc_pie
+ LOCAL_SRC_FILES := vdc_pie.cpp
+ LOCAL_MODULE_TAGS := eng
+ LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
+ LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
+ LOCAL_CLANG := true
+ LOCAL_TIDY := true
+ LOCAL_TIDY_FLAGS := -warnings-as-errors=clang-analyzer-security*,cert-*
+ LOCAL_TIDY_CHECKS := -*,cert-*,clang,-analyzer-security*
+ LOCAL_STATIC_LIBRARIES := libvold_binder
+ LOCAL_SHARED_LIBRARIES := libbase libcutils libutils libbinder
+ LOCAL_CFLAGS := -Wall
+ ifeq ($(TWRP_INCLUDE_LOGCAT), true)
+ LOCAL_CFLAGS += -DTWRP_INCLUDE_LOGCAT
+ endif
+ ifneq ($(TARGET_ARCH), arm64)
+ ifneq ($(TARGET_ARCH), x86_64)
+ LOCAL_LDFLAGS += -Wl,-dynamic-linker,/sbin/linker
+ else
+ LOCAL_LDFLAGS += -Wl,-dynamic-linker,/sbin/linker64
+ endif
+ else
+ LOCAL_LDFLAGS += -Wl,-dynamic-linker,/sbin/linker64
+ endif
+
+ include $(BUILD_EXECUTABLE)
+ endif
+
endif
endif
diff --git a/crypto/vold_decrypt/init.recovery.vold_decrypt.servicemanager.rc b/crypto/vold_decrypt/init.recovery.vold_decrypt.servicemanager.rc
new file mode 100644
index 000000000..40672d737
--- /dev/null
+++ b/crypto/vold_decrypt/init.recovery.vold_decrypt.servicemanager.rc
@@ -0,0 +1,8 @@
+service sys_servicemanager /system/bin/servicemanager
+ user root
+ group root
+ setenv PATH /system/bin
+ setenv LD_LIBRARY_PATH /system/lib64:/system/lib
+ disabled
+ oneshot
+ seclabel u:r:vold:s0
diff --git a/crypto/vold_decrypt/vdc_pie.cpp b/crypto/vold_decrypt/vdc_pie.cpp
new file mode 100644
index 000000000..a84071213
--- /dev/null
+++ b/crypto/vold_decrypt/vdc_pie.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <poll.h>
+
+#include <cutils/properties.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include "android/os/IVold.h"
+
+#include <binder/IServiceManager.h>
+#include <binder/Status.h>
+
+#include <private/android_filesystem_config.h>
+
+static void usage();
+
+static android::sp<android::IBinder> getServiceAggressive() {
+ static char prop_value[PROPERTY_VALUE_MAX];
+ property_get("init.svc.sys_vold", prop_value, "error");
+ if (strncmp(prop_value, "running", strlen("running")) != 0) {
+ printf("vdc_pie: vold is not running, init.svc.sys_vold=%s\n", prop_value);
+ exit(EINVAL);
+ }
+
+ android::sp<android::IBinder> res;
+ auto sm = android::defaultServiceManager();
+ auto name = android::String16("vold");
+ for (int i = 0; i < 5000; i++) {
+ res = sm->checkService(name);
+ if (res) {
+ printf("vdc_pie: Got vold, waited %d ms\n", (i * 10));
+ break;
+ }
+ usleep(10000); // 10ms
+ }
+ return res;
+}
+
+static int checkStatus(android::binder::Status status) {
+ if (status.isOk()) return 0;
+ std::string ret = status.toString8().string();
+#ifdef TWRP_INCLUDE_LOGCAT
+ printf("vdc_pie: Decryption failed, vold service returned: %s,"
+ " see logcat for details\n", ret.c_str());
+#else
+ printf("vdc_pie: Decryption failed, vold service returned: %s\n", ret.c_str());
+#endif
+ return -1;
+}
+
+int main(int argc, char** argv) {
+ std::vector<std::string> args(argv + 1, argv + argc);
+
+ if (args.size() > 0 && args[0] == "--wait") {
+ // Just ignore the --wait flag
+ args.erase(args.begin());
+ }
+
+ if (args.size() < 2) {
+ usage();
+ exit(5);
+ }
+ android::sp<android::IBinder> binder = getServiceAggressive();
+ if (!binder) {
+ printf("vdc_pie: Failed to obtain vold Binder\n");
+ exit(EINVAL);
+ }
+ auto vold = android::interface_cast<android::os::IVold>(binder);
+
+ if (args[0] == "cryptfs" && args[1] == "checkpw" && args.size() == 3) {
+ return checkStatus(vold->fdeCheckPassword(args[2]));
+ } else {
+ usage();
+ exit(EINVAL);
+ }
+ return 0;
+}
+
+static void usage() {
+ printf("vdc_pie: Usage: vold_pie cryptfs checkpw <password>\n");
+}
diff --git a/crypto/vold_decrypt/vold_decrypt.cpp b/crypto/vold_decrypt/vold_decrypt.cpp
index ded4e7b67..ac872ea28 100644
--- a/crypto/vold_decrypt/vold_decrypt.cpp
+++ b/crypto/vold_decrypt/vold_decrypt.cpp
@@ -74,6 +74,7 @@ namespace {
#define LOGERROR(...) do { printf(__VA_ARGS__); if (fp_kmsg) { fprintf(fp_kmsg, "[VOLD_DECRYPT]E:" __VA_ARGS__); fflush(fp_kmsg); } } while (0)
FILE *fp_kmsg = NULL;
+int sdkver = 20;
/* Debugging Functions */
@@ -223,7 +224,7 @@ string Wait_For_Property(const string& property_name, int utimeout = SLEEP_MAX_U
break;
LOGKMSG("waiting for %s to change from '%s' to '%s'\n", property_name.c_str(), prop_value, expected_value.c_str());
utimeout -= SLEEP_MIN_USEC;
- usleep(SLEEP_MIN_USEC);;
+ usleep(SLEEP_MIN_USEC);
}
}
property_get(property_name.c_str(), prop_value, "error");
@@ -766,7 +767,6 @@ vector<AdditionalService> Get_List_Of_Additional_Services(void) {
void Set_Needed_Properties(void) {
// vold won't start without ro.storage_structure on Kitkat
string sdkverstr = TWFunc::System_Property_Get("ro.build.version.sdk");
- int sdkver = 20;
if (!sdkverstr.empty()) {
sdkver = atoi(sdkverstr.c_str());
}
@@ -775,8 +775,79 @@ void Set_Needed_Properties(void) {
if (!ro_storage_structure.empty())
property_set("ro.storage_structure", ro_storage_structure.c_str());
}
+ property_set("hwservicemanager.ready", "false");
+ property_set("sys.listeners.registered", "false");
+ property_set("vendor.sys.listeners.registered", "false");
}
+static unsigned int get_blkdev_size(int fd) {
+ unsigned long nr_sec;
+
+ if ( (ioctl(fd, BLKGETSIZE, &nr_sec)) == -1) {
+ nr_sec = 0;
+ }
+
+ return (unsigned int) nr_sec;
+}
+
+#define CRYPT_FOOTER_OFFSET 0x4000
+static char footer[16 * 1024];
+const char* userdata_path;
+static off64_t offset;
+
+int footer_br(const string& command) {
+ int fd;
+
+ if (command == "backup") {
+ unsigned int nr_sec;
+ TWPartition* userdata = PartitionManager.Find_Partition_By_Path("/data");
+ userdata_path = userdata->Actual_Block_Device.c_str();
+ fd = open(userdata_path, O_RDONLY);
+ if (fd < 0) {
+ LOGERROR("E:footer_backup: Cannot open '%s': %s\n", userdata_path, strerror(errno));
+ return -1;
+ }
+ if ((nr_sec = get_blkdev_size(fd))) {
+ offset = ((off64_t)nr_sec * 512) - CRYPT_FOOTER_OFFSET;
+ } else {
+ LOGERROR("E:footer_br: Failed to get offset\n");
+ close(fd);
+ return -1;
+ }
+ if (lseek64(fd, offset, SEEK_SET) == -1) {
+ LOGERROR("E:footer_backup: Failed to lseek64\n");
+ close(fd);
+ return -1;
+ }
+ if (read(fd, footer, sizeof(footer)) != sizeof(footer)) {
+ LOGERROR("E:footer_br: Failed to read: %s\n", strerror(errno));
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ } else if (command == "restore") {
+ fd = open(userdata_path, O_WRONLY);
+ if (fd < 0) {
+ LOGERROR("E:footer_restore: Cannot open '%s': %s\n", userdata_path, strerror(errno));
+ return -1;
+ }
+ if (lseek64(fd, offset, SEEK_SET) == -1) {
+ LOGERROR("E:footer_restore: Failed to lseek64\n");
+ close(fd);
+ return -1;
+ }
+ if (write(fd, footer, sizeof(footer)) != sizeof(footer)) {
+ LOGERROR("E:footer_br: Failed to write: %s\n", strerror(errno));
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ } else {
+ LOGERROR("E:footer_br: wrong command argument: %s\n", command.c_str());
+ return -1;
+ }
+ return 0;
+}
/* vdc Functions */
typedef struct {
@@ -801,9 +872,14 @@ int Exec_vdc_cryptfs(const string& command, const string& argument, vdc_ReturnVa
}
}
- const char *cmd[] = { "/system/bin/vdc", "cryptfs" };
+ // getpwtype and checkpw commands are removed from Pie vdc, using modified vdc_pie
+ const char *cmd[] = { "/sbin/vdc_pie", "cryptfs" };
+ if (sdkver < 28)
+ cmd[0] = "/system/bin/vdc";
const char *env[] = { "LD_LIBRARY_PATH=/system/lib64:/system/lib", NULL };
+ LOGINFO("sdkver: %d, using %s\n", sdkver, cmd[0]);
+
#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
string log_name = "/tmp/strace_vdc_" + command;
#endif
@@ -918,6 +994,9 @@ int Exec_vdc_cryptfs(const string& command, const string& argument, vdc_ReturnVa
return -1;
}
}
+ if (sdkver >= 28) {
+ return WEXITSTATUS(status);
+ }
return 0;
}
}
@@ -930,32 +1009,34 @@ int Run_vdc(const string& Password) {
LOGINFO("About to run vdc...\n");
- // Wait for vold connection
- gettimeofday(&t1, NULL);
- t2 = t1;
- while ((t2.tv_sec - t1.tv_sec) < 5) {
- // cryptfs getpwtype returns: R1=213(PasswordTypeResult) R2=? R3="password", "pattern", "pin", "default"
- res = Exec_vdc_cryptfs("getpwtype", "", &vdcResult);
- if (vdcResult.ResponseCode == PASSWORD_TYPE_RESULT) {
- res = 0;
- break;
+ // Pie vdc communicates with vold directly, no socket so lets not waste time
+ if (sdkver < 28) {
+ // Wait for vold connection
+ gettimeofday(&t1, NULL);
+ t2 = t1;
+ while ((t2.tv_sec - t1.tv_sec) < 5) {
+ // cryptfs getpwtype returns: R1=213(PasswordTypeResult) R2=? R3="password", "pattern", "pin", "default"
+ res = Exec_vdc_cryptfs("getpwtype", "", &vdcResult);
+ if (vdcResult.ResponseCode == PASSWORD_TYPE_RESULT) {
+ res = 0;
+ break;
+ }
+ LOGINFO("Retrying connection to vold (Reason: %s)\n", vdcResult.Output.c_str());
+ usleep(SLEEP_MIN_USEC); // vdc usually usleep(10000), but that causes too many unnecessary attempts
+ gettimeofday(&t2, NULL);
}
- LOGINFO("Retrying connection to vold (Reason: %s)\n", vdcResult.Output.c_str());
- usleep(SLEEP_MIN_USEC); // vdc usually usleep(10000), but that causes too many unnecessary attempts
- gettimeofday(&t2, NULL);
- }
-
- if (res == 0 && (t2.tv_sec - t1.tv_sec) < 5)
- LOGINFO("Connected to vold: %s\n", vdcResult.Output.c_str());
- else if (res == VD_ERR_VOLD_OPERATION_TIMEDOUT)
- return VD_ERR_VOLD_OPERATION_TIMEDOUT; // should never happen for getpwtype
- else if (res)
- return VD_ERR_FORK_EXECL_ERROR;
- else if (vdcResult.ResponseCode != -1)
- return VD_ERR_VOLD_UNEXPECTED_RESPONSE;
- else
- return VD_ERR_VDC_FAILED_TO_CONNECT;
+ if (res == 0 && (t2.tv_sec - t1.tv_sec) < 5)
+ LOGINFO("Connected to vold: %s\n", vdcResult.Output.c_str());
+ else if (res == VD_ERR_VOLD_OPERATION_TIMEDOUT)
+ return VD_ERR_VOLD_OPERATION_TIMEDOUT; // should never happen for getpwtype
+ else if (res)
+ return VD_ERR_FORK_EXECL_ERROR;
+ else if (vdcResult.ResponseCode != -1)
+ return VD_ERR_VOLD_UNEXPECTED_RESPONSE;
+ else
+ return VD_ERR_VDC_FAILED_TO_CONNECT;
+ }
// Input password from GUI, or default password
res = Exec_vdc_cryptfs("checkpw", Password, &vdcResult);
@@ -970,6 +1051,12 @@ int Run_vdc(const string& Password) {
return VD_ERR_VOLD_UNEXPECTED_RESPONSE;
*/
+ // our vdc returns vold binder op status,
+ // we care about status.ok() only which is 0
+ if (sdkver >= 28) {
+ vdcResult.Message = res;
+ }
+
if (vdcResult.Message != 0) {
// try falling back to Lollipop hex passwords
string hexPassword = convert_key_to_hex_ascii(Password);
@@ -986,8 +1073,9 @@ int Run_vdc(const string& Password) {
*/
}
- // vdc's return value is dependant upon source origin, it will either
+ // sdk < 28 vdc's return value is dependant upon source origin, it will either
// return 0 or ResponseCode, so disregard and focus on decryption instead
+ // our vdc always returns 0 on success
if (vdcResult.Message == 0) {
// Decryption successful wait for crypto blk dev
Wait_For_Property("ro.crypto.fs_crypto_blkdev");
@@ -1013,17 +1101,31 @@ int Vold_Decrypt_Core(const string& Password) {
return VD_ERR_PASSWORD_EMPTY;
}
- // Mount system and check for vold and vdc
- if (!PartitionManager.Mount_By_Path("/system", true)) {
+ // Mount ANDROID_ROOT and check for vold and vdc
+ if (!PartitionManager.Mount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) {
return VD_ERR_UNABLE_TO_MOUNT_SYSTEM;
- } else if (!TWFunc::Path_Exists("/system/bin/vold")) {
- LOGINFO("ERROR: /system/bin/vold not found, aborting.\n");
+ } else if ((!TWFunc::Path_Exists("/system/bin/vold")) && (!TWFunc::Path_Exists(PartitionManager.Get_Android_Root_Path() + "/system/bin/vold"))) {
+ LOGINFO("ERROR: vold not found, aborting.\n");
return VD_ERR_MISSING_VOLD;
- } else if (!TWFunc::Path_Exists("/system/bin/vdc")) {
- LOGINFO("ERROR: /system/bin/vdc not found, aborting.\n");
+ } else if ((!TWFunc::Path_Exists("/system/bin/vdc")) && (!TWFunc::Path_Exists(PartitionManager.Get_Android_Root_Path() + "/system/bin/vdc"))) {
+ LOGINFO("ERROR: vdc not found, aborting.\n");
return VD_ERR_MISSING_VDC;
}
+#ifdef TW_CRYPTO_SYSTEM_VOLD_MOUNT
+ vector<string> partitions = TWFunc::Split_String(TW_CRYPTO_SYSTEM_VOLD_MOUNT, " ");
+ for (size_t i = 0; i < partitions.size(); ++i) {
+ string mnt_point = "/" + partitions[i];
+ if(PartitionManager.Find_Partition_By_Path(mnt_point)) {
+ if (!PartitionManager.Mount_By_Path(mnt_point, true)) {
+ LOGERROR("Unable to mount %s\n", mnt_point.c_str());
+ return VD_ERR_UNABLE_TO_MOUNT_EXTRA;
+ }
+ LOGINFO("%s partition mounted\n", partitions[i].c_str());
+ }
+ }
+#endif
+
fp_kmsg = fopen("/dev/kmsg", "a");
LOGINFO("TW_CRYPTO_USE_SYSTEM_VOLD := true\n");
@@ -1064,8 +1166,20 @@ int Vold_Decrypt_Core(const string& Password) {
LOGINFO("Starting services...\n");
#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
for (size_t i = 0; i < Services.size(); ++i) {
- if (Services[i].bin_exists)
+ if (Services[i].bin_exists) {
+ if (Services[i].Service_Binary.find("keymaster") != string::npos) {
+ Wait_For_Property("hwservicemanager.ready", 500000, "true");
+ LOGINFO(" hwservicemanager is ready.\n");
+ }
+
Services[i].is_running = Start_Service(Services[i].VOLD_Service_Name);
+
+ if (Services[i].Service_Binary == "qseecomd") {
+ if (Wait_For_Property("sys.listeners.registered", 500000, "true") == "true"
+ || Wait_For_Property("vendor.sys.listeners.registered", 500000, "true") == "true")
+ LOGINFO(" qseecomd listeners registered.\n");
+ }
+ }
}
#endif
is_vold_running = Start_Service("sys_vold");
@@ -1080,7 +1194,29 @@ int Vold_Decrypt_Core(const string& Password) {
}
}
#endif
- res = Run_vdc(Password);
+
+ /*
+ * Oreo and Pie vold on some devices alters footer causing
+ * system to ask for decryption password at next boot although
+ * password haven't changed so we save footer before and restore it
+ * after vold operations
+ */
+ if (sdkver > 25) {
+ if (footer_br("backup") == 0) {
+ LOGINFO("footer_br: crypto footer backed up\n");
+ res = Run_vdc(Password);
+ if (footer_br("restore") == 0)
+ LOGINFO("footer_br: crypto footer restored\n");
+ else
+ LOGERROR("footer_br: Failed to restore crypto footer\n");
+ } else {
+ LOGERROR("footer_br: Failed to backup crypto footer, \
+ skipping decrypt to prevent data loss. Reboot recovery to try again...\n");
+ res = -1;
+ }
+ } else {
+ res = Run_vdc(Password);
+ }
if (res != 0) {
LOGINFO("Decryption failed\n");
@@ -1109,20 +1245,45 @@ int Vold_Decrypt_Core(const string& Password) {
if (is_fstab_symlinked)
Restore_Recovery_Fstab();
- if (!PartitionManager.UnMount_By_Path("/system", true)) {
- // PartitionManager failed to unmount /system, this should not happen,
+ if (!PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) {
+ // PartitionManager failed to unmount ANDROID_ROOT, this should not happen,
// but in case it does, do a lazy unmount
- LOGINFO("WARNING: system could not be unmounted normally!\n");
- umount2("/system", MNT_DETACH);
+ LOGINFO("WARNING: '%s' could not be unmounted normally!\n", PartitionManager.Get_Android_Root_Path().c_str());
+ umount2(PartitionManager.Get_Android_Root_Path().c_str(), MNT_DETACH);
+ }
+
+#ifdef TW_CRYPTO_SYSTEM_VOLD_MOUNT
+ for (size_t i = 0; i < partitions.size(); ++i) {
+ string mnt_point = "/" + partitions[i];
+ if(PartitionManager.Is_Mounted_By_Path(mnt_point)) {
+ if (!PartitionManager.UnMount_By_Path(mnt_point, true)) {
+ LOGINFO("WARNING: %s partition could not be unmounted normally!\n", partitions[i].c_str());
+ umount2(mnt_point.c_str(), MNT_DETACH);
+ }
+ }
}
+#endif
LOGINFO("Finished.\n");
#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
+ Set_Needed_Properties();
// Restart previously running services
for (size_t i = 0; i < Services.size(); ++i) {
- if (Services[i].resume)
+ if (Services[i].resume) {
+ if (Services[i].Service_Binary.find("keymaster") != string::npos) {
+ Wait_For_Property("hwservicemanager.ready", 500000, "true");
+ LOGINFO(" hwservicemanager is ready.\n");
+ }
+
Start_Service(Services[i].TWRP_Service_Name);
+
+ if (Services[i].Service_Binary == "qseecomd") {
+ if (Wait_For_Property("sys.listeners.registered", 500000, "true") == "true"
+ || Wait_For_Property("vendor.sys.listeners.registered", 500000, "true") == "true")
+ LOGINFO(" qseecomd listeners registered.\n");
+ }
+ }
}
#endif
diff --git a/crypto/vold_decrypt/vold_decrypt.h b/crypto/vold_decrypt/vold_decrypt.h
index ba7a74720..248a42786 100644
--- a/crypto/vold_decrypt/vold_decrypt.h
+++ b/crypto/vold_decrypt/vold_decrypt.h
@@ -34,6 +34,7 @@ enum {
VD_ERR_VOLD_OPERATION_TIMEDOUT = -8,
VD_ERR_FORK_EXECL_ERROR = -9,
VD_ERR_PASSWORD_EMPTY = -10,
+ VD_ERR_UNABLE_TO_MOUNT_EXTRA = -11,
};
diff --git a/data.cpp b/data.cpp
index 4dfbde2d0..d9239a473 100644
--- a/data.cpp
+++ b/data.cpp
@@ -146,6 +146,16 @@ void DataManager::get_device_id(void) {
#endif
#ifndef TW_FORCE_CPUINFO_FOR_DEVICE_ID
+#ifdef TW_USE_SERIALNO_PROPERTY_FOR_DEVICE_ID
+ // Check serial number system property
+ if (property_get("ro.serialno", line, "")) {
+ snprintf(device_id, DEVID_MAX, "%s", line);
+ sanitize_device_id(device_id);
+ mConst.SetValue("device_id", device_id);
+ return;
+ }
+#endif
+
// Check the cmdline to see if the serial number was supplied
fp = fopen("/proc/cmdline", "rt");
if (fp != NULL) {
@@ -757,10 +767,10 @@ void DataManager::SetDefaultValues()
mPersist.SetValue("tw_military_time", "0");
#ifdef TW_INCLUDE_CRYPTO
- mConst.SetValue(TW_USE_SHA2, "1");
- mConst.SetValue(TW_NO_SHA2, "0");
+ mPersist.SetValue(TW_USE_SHA2, "1");
+ mPersist.SetValue(TW_NO_SHA2, "0");
#else
- mConst.SetValue(TW_NO_SHA2, "1");
+ mPersist.SetValue(TW_NO_SHA2, "1");
#endif
#ifdef TW_NO_SCREEN_TIMEOUT
diff --git a/etc/Android.mk b/etc/Android.mk
index cda0f372e..4aeb251dc 100644
--- a/etc/Android.mk
+++ b/etc/Android.mk
@@ -88,3 +88,18 @@ ifeq ($(TWRP_INCLUDE_LOGCAT), true)
include $(BUILD_PREBUILT)
endif
endif
+
+ifeq ($(TW_USE_TOOLBOX), true)
+ include $(CLEAR_VARS)
+ LOCAL_MODULE := init.recovery.mksh.rc
+ LOCAL_MODULE_TAGS := eng
+ LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
+
+ # Cannot send to TARGET_RECOVERY_ROOT_OUT since build system wipes init*.rc
+ # during ramdisk creation and only allows init.recovery.*.rc files to be copied
+ # from TARGET_ROOT_OUT thereafter
+ LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
+
+ LOCAL_SRC_FILES := $(LOCAL_MODULE)
+ include $(BUILD_PREBUILT)
+endif
diff --git a/etc/init.rc b/etc/init.rc
index bcd519b03..348471d4f 100644
--- a/etc/init.rc
+++ b/etc/init.rc
@@ -1,4 +1,5 @@
import /init.recovery.logd.rc
+import /init.recovery.mksh.rc
import /init.recovery.usb.rc
import /init.recovery.service.rc
import /init.recovery.vold_decrypt.rc
diff --git a/etc/init.recovery.mksh.rc b/etc/init.recovery.mksh.rc
new file mode 100755
index 000000000..3afd946f3
--- /dev/null
+++ b/etc/init.recovery.mksh.rc
@@ -0,0 +1,2 @@
+on init
+ export ENV /etc/mkshrc
diff --git a/etc/init.recovery.service22.rc b/etc/init.recovery.service22.rc
index 43a3374b4..bb2853c1a 100644
--- a/etc/init.recovery.service22.rc
+++ b/etc/init.recovery.service22.rc
@@ -1,11 +1,5 @@
on boot
- export LD_CONFIG_FILE /sbin/ld.config.txt
# For starting recovery on 5.0 and newer
service recovery /sbin/recovery
seclabel u:r:recovery:s0
-
-# This helps fix ld.config.txt errors from the linker on Android 8.1
-service ldconfigtxt /sbin/touch /sbin/ld.config.txt
- oneshot
- seclabel u:r:recovery:s0
diff --git a/gui/action.cpp b/gui/action.cpp
index fb05d77b4..d708dd467 100644
--- a/gui/action.cpp
+++ b/gui/action.cpp
@@ -1819,14 +1819,14 @@ int GUIAction::checkpartitionlifetimewrites(std::string arg)
int GUIAction::mountsystemtoggle(std::string arg)
{
int op_status = 0;
- bool remount_system = PartitionManager.Is_Mounted_By_Path("/system");
+ bool remount_system = PartitionManager.Is_Mounted_By_Path(PartitionManager.Get_Android_Root_Path());
bool remount_vendor = PartitionManager.Is_Mounted_By_Path("/vendor");
operation_start("Toggle System Mount");
- if (!PartitionManager.UnMount_By_Path("/system", true)) {
+ if (!PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) {
op_status = 1; // fail
} else {
- TWPartition* Part = PartitionManager.Find_Partition_By_Path("/system");
+ TWPartition* Part = PartitionManager.Find_Partition_By_Path(PartitionManager.Get_Android_Root_Path());
if (Part) {
if (arg == "0") {
DataManager::SetValue("tw_mount_system_ro", 0);
@@ -1910,9 +1910,9 @@ int GUIAction::checkforapp(std::string arg __unused)
DataManager::SetValue("tw_app_install_status", 1); // 0 = no status, 1 = not installed, 2 = already installed or do not install
goto exit;
}
- if (PartitionManager.Mount_By_Path("/system", false)) {
- string base_path = "/system";
- if (TWFunc::Path_Exists("/system/system"))
+ if (PartitionManager.Mount_By_Path(PartitionManager.Get_Android_Root_Path(), false)) {
+ string base_path = PartitionManager.Get_Android_Root_Path();
+ if (TWFunc::Path_Exists(PartitionManager.Get_Android_Root_Path() + "/system"))
base_path += "/system"; // For devices with system as a root file system (e.g. Pixel)
string install_path = base_path + "/priv-app";
if (!TWFunc::Path_Exists(install_path))
@@ -2007,9 +2007,9 @@ int GUIAction::installapp(std::string arg __unused)
sync();
}
} else {
- if (PartitionManager.Mount_By_Path("/system", true)) {
- string base_path = "/system";
- if (TWFunc::Path_Exists("/system/system"))
+ if (PartitionManager.Mount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) {
+ string base_path = PartitionManager.Get_Android_Root_Path();
+ if (TWFunc::Path_Exists(PartitionManager.Get_Android_Root_Path() + "/system"))
base_path += "/system"; // For devices with system as a root file system (e.g. Pixel)
string install_path = base_path + "/priv-app";
string context = "u:object_r:system_file:s0";
@@ -2034,7 +2034,7 @@ int GUIAction::installapp(std::string arg __unused)
}
sync();
sync();
- PartitionManager.UnMount_By_Path("/system", true);
+ PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), true);
op_status = 0;
} else {
LOGERR("Error making app directory '%s': %s\n", strerror(errno));
diff --git a/gui/theme/landscape_hdpi/ui.xml b/gui/theme/landscape_hdpi/ui.xml
index 39f626f61..f1bd647f2 100644
--- a/gui/theme/landscape_hdpi/ui.xml
+++ b/gui/theme/landscape_hdpi/ui.xml
@@ -430,6 +430,11 @@
<action function="key">back</action>
</button>
+ <fill color="%background_color%">
+ <condition var1="tw_busy" var2="1"/>
+ <placement x="0" y="%navbar_y%" w="%screen_width%" h="%navbar_height%"/>
+ </fill>
+
<action>
<touch key="power"/>
<action function="togglebacklight"/>
diff --git a/gui/theme/landscape_mdpi/ui.xml b/gui/theme/landscape_mdpi/ui.xml
index cde1a5b76..cf30d898d 100644
--- a/gui/theme/landscape_mdpi/ui.xml
+++ b/gui/theme/landscape_mdpi/ui.xml
@@ -430,6 +430,11 @@
<action function="key">back</action>
</button>
+ <fill color="%background_color%">
+ <condition var1="tw_busy" var2="1"/>
+ <placement x="0" y="%navbar_y%" w="%screen_width%" h="%navbar_height%"/>
+ </fill>
+
<action>
<touch key="power"/>
<action function="togglebacklight"/>
diff --git a/gui/theme/portrait_hdpi/ui.xml b/gui/theme/portrait_hdpi/ui.xml
index 0545b3f6b..3f3102a5e 100644
--- a/gui/theme/portrait_hdpi/ui.xml
+++ b/gui/theme/portrait_hdpi/ui.xml
@@ -334,6 +334,11 @@
<action function="key">back</action>
</button>
+ <fill color="%background_color%">
+ <condition var1="tw_busy" var2="1"/>
+ <placement x="0" y="%navbar_y%" w="%screen_width%" h="%navbar_height%"/>
+ </fill>
+
<action>
<touch key="power"/>
<action function="togglebacklight"/>
diff --git a/gui/theme/portrait_mdpi/ui.xml b/gui/theme/portrait_mdpi/ui.xml
index 061d46b0e..f41ff79cb 100644
--- a/gui/theme/portrait_mdpi/ui.xml
+++ b/gui/theme/portrait_mdpi/ui.xml
@@ -334,6 +334,11 @@
<action function="key">back</action>
</button>
+ <fill color="%background_color%">
+ <condition var1="tw_busy" var2="1"/>
+ <placement x="0" y="%navbar_y%" w="%screen_width%" h="%navbar_height%"/>
+ </fill>
+
<action>
<touch key="power"/>
<action function="togglebacklight"/>
diff --git a/minui/events.cpp b/minui/events.cpp
index f67684b8b..c7779961a 100644
--- a/minui/events.cpp
+++ b/minui/events.cpp
@@ -24,7 +24,6 @@
#include <sys/epoll.h>
#include <sys/ioctl.h>
#include <unistd.h>
-#include <errno.h>
#include <functional>
diff --git a/minui/graphics_overlay.cpp b/minui/graphics_overlay.cpp
index b7e62d945..5988d70ad 100644
--- a/minui/graphics_overlay.cpp
+++ b/minui/graphics_overlay.cpp
@@ -448,12 +448,10 @@ GRSurface* MinuiBackendOverlay::Flip() {
if (double_buffered) {
#if defined(RECOVERY_BGRA)
// In case of BGRA, do some byte swapping
- unsigned int idx;
- unsigned char tmp;
unsigned char* ucfb_vaddr = (unsigned char*)gr_draw->data;
- for (idx = 0 ; idx < (gr_draw->height * gr_draw->row_bytes);
+ for (int idx = 0 ; idx < (gr_draw->height * gr_draw->row_bytes);
idx += 4) {
- tmp = ucfb_vaddr[idx];
+ unsigned char tmp = ucfb_vaddr[idx];
ucfb_vaddr[idx ] = ucfb_vaddr[idx + 2];
ucfb_vaddr[idx + 2] = tmp;
}
diff --git a/minuitwrp/Android.mk b/minuitwrp/Android.mk
index 09bdb8d48..0f8aae6d3 100644
--- a/minuitwrp/Android.mk
+++ b/minuitwrp/Android.mk
@@ -34,7 +34,7 @@ else
LOCAL_C_INCLUDES += $(commands_recovery_local_path)/minuitwrp/include
# The header files required for adf graphics can cause compile errors
# with adf graphics.
- ifneq ($(wildcard system/core/adf/Android.mk),)
+ ifneq ($(wildcard system/core/adf/Android.*),)
LOCAL_CFLAGS += -DHAS_ADF
LOCAL_SRC_FILES += graphics_adf.cpp
LOCAL_WHOLE_STATIC_LIBRARIES += libadf
@@ -45,7 +45,7 @@ ifeq ($(TW_NEW_ION_HEAP), true)
LOCAL_CFLAGS += -DNEW_ION_HEAP
endif
-ifneq ($(wildcard external/libdrm/Android.mk),)
+ifneq ($(wildcard external/libdrm/Android.*),)
LOCAL_CFLAGS += -DHAS_DRM
LOCAL_SRC_FILES += graphics_drm.cpp
ifneq ($(wildcard external/libdrm/Android.common.mk),)
diff --git a/minuitwrp/events.cpp b/minuitwrp/events.cpp
index 94b800ea6..bd29f718d 100644
--- a/minuitwrp/events.cpp
+++ b/minuitwrp/events.cpp
@@ -26,7 +26,7 @@
#include <unistd.h>
#include <stdio.h>
#include <string.h>
-
+#include <fstream>
#include "../common.h"
@@ -39,6 +39,9 @@
#define VIBRATOR_TIMEOUT_FILE "/sys/class/timed_output/vibrator/enable"
#define VIBRATOR_TIME_MS 50
+#define LEDS_HAPTICS_DURATION_FILE "/sys/class/leds/vibrator/duration"
+#define LEDS_HAPTICS_ACTIVATE_FILE "/sys/class/leds/vibrator/activate"
+
#ifndef SYN_REPORT
#define SYN_REPORT 0x00
#endif
@@ -108,24 +111,27 @@ static inline int ABS(int x) {
return x<0?-x:x;
}
+int write_to_file(const std::string& fn, const std::string& line) {
+ FILE *file;
+ file = fopen(fn.c_str(), "w");
+ if (file != NULL) {
+ fwrite(line.c_str(), line.size(), 1, file);
+ fclose(file);
+ return 0;
+ }
+ LOGI("Cannot find file %s\n", fn.c_str());
+ return -1;
+}
+
int vibrate(int timeout_ms)
{
- char str[20];
- int fd;
- int ret;
-
if (timeout_ms > 10000) timeout_ms = 1000;
- fd = open(VIBRATOR_TIMEOUT_FILE, O_WRONLY);
- if (fd < 0)
- return -1;
-
- ret = snprintf(str, sizeof(str), "%d", timeout_ms);
- ret = write(fd, str, ret);
- close(fd);
-
- if (ret < 0)
- return -1;
+ if (std::ifstream(LEDS_HAPTICS_ACTIVATE_FILE).good()) {
+ write_to_file(LEDS_HAPTICS_DURATION_FILE, std::to_string(timeout_ms));
+ write_to_file(LEDS_HAPTICS_ACTIVATE_FILE, "1");
+ } else
+ write_to_file(VIBRATOR_TIMEOUT_FILE, std::to_string(timeout_ms));
return 0;
}
diff --git a/minuitwrp/graphics.cpp b/minuitwrp/graphics.cpp
index 81e77a630..d914eef3d 100644
--- a/minuitwrp/graphics.cpp
+++ b/minuitwrp/graphics.cpp
@@ -157,7 +157,11 @@ gr_surface gr_render_circle(int radius, unsigned char r, unsigned char g, unsign
surface->height = diameter;
surface->stride = diameter;
surface->data = (GGLubyte*)data;
+#if defined(RECOVERY_BGRA)
+ surface->format = GGL_PIXEL_FORMAT_BGRA_8888;
+#else
surface->format = GGL_PIXEL_FORMAT_RGBA_8888;
+#endif
for(ry = -radius; ry <= radius; ++ry)
for(rx = -radius; rx <= radius; ++rx)
diff --git a/minuitwrp/graphics_adf.cpp b/minuitwrp/graphics_adf.cpp
index b71bed2a8..7b37271ec 100644
--- a/minuitwrp/graphics_adf.cpp
+++ b/minuitwrp/graphics_adf.cpp
@@ -136,7 +136,6 @@ done:
static int adf_device_init(adf_pdata *pdata, adf_device *dev)
{
adf_id_t intf_id;
- int intf_fd;
int err;
err = adf_find_simple_post_configuration(dev, &pdata->format, 1, &intf_id,
diff --git a/minuitwrp/graphics_drm.cpp b/minuitwrp/graphics_drm.cpp
index c321bb7d8..409a12378 100644
--- a/minuitwrp/graphics_drm.cpp
+++ b/minuitwrp/graphics_drm.cpp
@@ -157,8 +157,8 @@ static drm_surface *drm_create_surface(int width, int height) {
printf("setting DRM_FORMAT_ABGR8888 and GGL_PIXEL_FORMAT_BGRA_8888, GGL_PIXEL_FORMAT may not match!\n");
#elif defined(RECOVERY_RGBX)
format = DRM_FORMAT_XBGR8888;
- base_format = GGL_PIXEL_FORMAT_BGRA_8888;
- printf("setting DRM_FORMAT_XBGR8888 and GGL_PIXEL_FORMAT_BGRA_8888, GGL_PIXEL_FORMAT may not match!\n");
+ base_format = GGL_PIXEL_FORMAT_RGBA_8888;
+ printf("setting DRM_FORMAT_XBGR8888 and GGL_PIXEL_FORMAT_RGBA_8888\n");
#else
format = DRM_FORMAT_RGB565;
base_format = GGL_PIXEL_FORMAT_BGRA_8888;
diff --git a/minuitwrp/graphics_fbdev.cpp b/minuitwrp/graphics_fbdev.cpp
index a1c42d05c..8cf85f5eb 100644
--- a/minuitwrp/graphics_fbdev.cpp
+++ b/minuitwrp/graphics_fbdev.cpp
@@ -285,12 +285,10 @@ static GRSurface* fbdev_init(minui_backend* backend) {
static GRSurface* fbdev_flip(minui_backend* backend __unused) {
#if defined(RECOVERY_BGRA)
// In case of BGRA, do some byte swapping
- unsigned int idx;
- unsigned char tmp;
unsigned char* ucfb_vaddr = (unsigned char*)gr_draw->data;
- for (idx = 0 ; idx < (gr_draw->height * gr_draw->row_bytes);
+ for (int idx = 0 ; idx < (gr_draw->height * gr_draw->row_bytes);
idx += 4) {
- tmp = ucfb_vaddr[idx];
+ unsigned char tmp = ucfb_vaddr[idx];
ucfb_vaddr[idx ] = ucfb_vaddr[idx + 2];
ucfb_vaddr[idx + 2] = tmp;
}
diff --git a/minuitwrp/graphics_overlay.cpp b/minuitwrp/graphics_overlay.cpp
index 84ea6e0ea..b4efae421 100644
--- a/minuitwrp/graphics_overlay.cpp
+++ b/minuitwrp/graphics_overlay.cpp
@@ -50,7 +50,6 @@ static void overlay_exit(minui_backend*);
static GRSurface gr_framebuffer;
static GRSurface* gr_draw = NULL;
-static int displayed_buffer;
static fb_var_screeninfo vi;
static int fb_fd = -1;
@@ -100,7 +99,6 @@ static minui_backend my_backend = {
bool target_has_overlay(char *version)
{
- int ret;
int mdp_version;
bool overlay_supported = false;
@@ -491,12 +489,10 @@ int overlay_display_frame(int fd, void* data, size_t size)
static GRSurface* overlay_flip(minui_backend* backend __unused) {
#if defined(RECOVERY_BGRA)
// In case of BGRA, do some byte swapping
- unsigned int idx;
- unsigned char tmp;
unsigned char* ucfb_vaddr = (unsigned char*)gr_draw->data;
- for (idx = 0 ; idx < (gr_draw->height * gr_draw->row_bytes);
+ for (int idx = 0 ; idx < (gr_draw->height * gr_draw->row_bytes);
idx += 4) {
- tmp = ucfb_vaddr[idx];
+ unsigned char tmp = ucfb_vaddr[idx];
ucfb_vaddr[idx ] = ucfb_vaddr[idx + 2];
ucfb_vaddr[idx + 2] = tmp;
}
diff --git a/minuitwrp/graphics_utils.cpp b/minuitwrp/graphics_utils.cpp
index 6ce570484..67c836ed5 100644
--- a/minuitwrp/graphics_utils.cpp
+++ b/minuitwrp/graphics_utils.cpp
@@ -52,7 +52,12 @@ int gr_save_screenshot(const char *dest)
surface.height = gr_mem_surface.height;
surface.stride = gr_mem_surface.stride;
surface.data = img_data;
+
+#if defined(RECOVERY_BGRA)
+ surface.format = GGL_PIXEL_FORMAT_BGRA_8888;
+#else
surface.format = GGL_PIXEL_FORMAT_RGBA_8888;
+#endif
gglInit(&gl);
gl->colorBuffer(gl, &surface);
diff --git a/openrecoveryscript.cpp b/openrecoveryscript.cpp
index d7e4a2332..86c90a662 100644
--- a/openrecoveryscript.cpp
+++ b/openrecoveryscript.cpp
@@ -147,8 +147,8 @@ int OpenRecoveryScript::run_script_file(void) {
// Wipe
if (strcmp(value, "cache") == 0 || strcmp(value, "/cache") == 0) {
PartitionManager.Wipe_By_Path("/cache");
- } else if (strcmp(value, "system") == 0 || strcmp(value, "/system") == 0) {
- PartitionManager.Wipe_By_Path("/system");
+ } else if (strcmp(value, PartitionManager.Get_Android_Root_Path().c_str()) == 0 || strcmp(value, PartitionManager.Get_Android_Root_Path().c_str()) == 0) {
+ PartitionManager.Wipe_By_Path(PartitionManager.Get_Android_Root_Path());
} else if (strcmp(value, "dalvik") == 0 || strcmp(value, "dalvick") == 0 || strcmp(value, "dalvikcache") == 0 || strcmp(value, "dalvickcache") == 0) {
PartitionManager.Wipe_Dalvik_Cache();
} else if (strcmp(value, "data") == 0 || strcmp(value, "/data") == 0 || strcmp(value, "factory") == 0 || strcmp(value, "factoryreset") == 0) {
@@ -667,14 +667,14 @@ void OpenRecoveryScript::Run_CLI_Command(const char* command) {
int OpenRecoveryScript::remountrw(void)
{
- bool remount_system = PartitionManager.Is_Mounted_By_Path("/system");
+ bool remount_system = PartitionManager.Is_Mounted_By_Path(PartitionManager.Get_Android_Root_Path());
int op_status;
TWPartition* Part;
- if (!PartitionManager.UnMount_By_Path("/system", true)) {
+ if (!PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) {
op_status = 1; // fail
} else {
- Part = PartitionManager.Find_Partition_By_Path("/system");
+ Part = PartitionManager.Find_Partition_By_Path(PartitionManager.Get_Android_Root_Path());
if (Part) {
DataManager::SetValue("tw_mount_system_ro", 0);
Part->Change_Mount_Read_Only(false);
diff --git a/partition.cpp b/partition.cpp
index e7b3d2d8a..8e30c3318 100644
--- a/partition.cpp
+++ b/partition.cpp
@@ -114,6 +114,8 @@ const struct flag_list mount_flags[] = {
const char *ignored_mount_items[] = {
"defaults=",
"errors=",
+ "latemount",
+ "sysfs_path=",
NULL
};
@@ -154,6 +156,7 @@ enum TW_FSTAB_FLAGS {
TWFLAG_VOLDMANAGED,
TWFLAG_FORMATTABLE,
TWFLAG_RESIZE,
+ TWFLAG_KEYDIRECTORY,
};
/* Flags without a trailing '=' are considered dual format flags and can be
@@ -197,6 +200,7 @@ const struct flag_list tw_flags[] = {
{ "voldmanaged=", TWFLAG_VOLDMANAGED },
{ "formattable", TWFLAG_FORMATTABLE },
{ "resize", TWFLAG_RESIZE },
+ { "keydirectory=", TWFLAG_KEYDIRECTORY },
{ 0, 0 },
};
@@ -260,6 +264,7 @@ TWPartition::TWPartition() {
Is_Adopted_Storage = false;
Adopted_GUID = "";
SlotSelect = false;
+ Key_Directory = "";
}
TWPartition::~TWPartition(void) {
@@ -430,7 +435,7 @@ bool TWPartition::Process_Fstab_Line(const char *fstab_line, bool Display_Error,
} else if (Is_File_System(Fstab_File_System)) {
Find_Actual_Block_Device();
Setup_File_System(Display_Error);
- if (Mount_Point == "/system") {
+ if (Mount_Point == PartitionManager.Get_Android_Root_Path()) {
Display_Name = "System";
Backup_Display_Name = Display_Name;
Storage_Name = Display_Name;
@@ -624,80 +629,39 @@ void TWPartition::Setup_Data_Partition(bool Display_Error) {
DataManager::SetValue(TW_IS_DECRYPTED, 1);
Is_Encrypted = true;
Is_Decrypted = true;
- Is_FBE = false;
+ if (Key_Directory.empty())
+ Is_FBE = false;
+ else
+ Is_FBE = true;
DataManager::SetValue(TW_IS_FBE, 0);
Decrypted_Block_Device = crypto_blkdev;
LOGINFO("Data already decrypted, new block device: '%s'\n", crypto_blkdev);
} else if (!Mount(false)) {
if (Is_Present) {
- set_partition_data(Actual_Block_Device.c_str(), Crypto_Key_Location.c_str(), Fstab_File_System.c_str());
- if (cryptfs_check_footer() == 0) {
+ if (Key_Directory.empty()) {
+ set_partition_data(Actual_Block_Device.c_str(), Crypto_Key_Location.c_str(), Fstab_File_System.c_str());
+ if (cryptfs_check_footer() == 0) {
+ Is_Encrypted = true;
+ Is_Decrypted = false;
+ Can_Be_Mounted = false;
+ Current_File_System = "emmc";
+ Setup_Image();
+ DataManager::SetValue(TW_IS_ENCRYPTED, 1);
+ DataManager::SetValue(TW_CRYPTO_PWTYPE, cryptfs_get_password_type());
+ DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
+ DataManager::SetValue("tw_crypto_display", "");
+ } else {
+ gui_err("mount_data_footer=Could not mount /data and unable to find crypto footer.");
+ }
+ } else {
Is_Encrypted = true;
Is_Decrypted = false;
- Can_Be_Mounted = false;
- Current_File_System = "emmc";
- Setup_Image();
- DataManager::SetValue(TW_IS_ENCRYPTED, 1);
- DataManager::SetValue(TW_CRYPTO_PWTYPE, cryptfs_get_password_type());
- DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
- DataManager::SetValue("tw_crypto_display", "");
- } else {
- gui_err("mount_data_footer=Could not mount /data and unable to find crypto footer.");
}
- } else {
+ } else if (Key_Directory.empty()) {
LOGERR("Primary block device '%s' for mount point '%s' is not present!\n", Primary_Block_Device.c_str(), Mount_Point.c_str());
}
} else {
- if (TWFunc::Path_Exists("/data/unencrypted/key/version")) {
- LOGINFO("File Based Encryption is present\n");
-#ifdef TW_INCLUDE_FBE
- ExcludeAll(Mount_Point + "/convert_fbe");
- ExcludeAll(Mount_Point + "/unencrypted");
- //ExcludeAll(Mount_Point + "/system/users/0"); // we WILL need to retain some of this if multiple users are present or we just need to delete more folders for the extra users somewhere else
- ExcludeAll(Mount_Point + "/misc/vold/user_keys");
- //ExcludeAll(Mount_Point + "/system_ce");
- //ExcludeAll(Mount_Point + "/system_de");
- //ExcludeAll(Mount_Point + "/misc_ce");
- //ExcludeAll(Mount_Point + "/misc_de");
- ExcludeAll(Mount_Point + "/system/gatekeeper.password.key");
- ExcludeAll(Mount_Point + "/system/gatekeeper.pattern.key");
- ExcludeAll(Mount_Point + "/system/locksettings.db");
- //ExcludeAll(Mount_Point + "/system/locksettings.db-shm"); // don't seem to need this one, but the other 2 are needed
- ExcludeAll(Mount_Point + "/system/locksettings.db-wal");
- //ExcludeAll(Mount_Point + "/user_de");
- //ExcludeAll(Mount_Point + "/misc/profiles/cur/0"); // might be important later
- ExcludeAll(Mount_Point + "/misc/gatekeeper");
- ExcludeAll(Mount_Point + "/misc/keystore");
- ExcludeAll(Mount_Point + "/drm/kek.dat");
- ExcludeAll(Mount_Point + "/system_de/0/spblob"); // contains data needed to decrypt pixel 2
- int retry_count = 3;
- while (!Decrypt_DE() && --retry_count)
- usleep(2000);
- if (retry_count > 0) {
- property_set("ro.crypto.state", "encrypted");
- Is_Encrypted = true;
- Is_Decrypted = false;
- Is_FBE = true;
- DataManager::SetValue(TW_IS_FBE, 1);
- DataManager::SetValue(TW_IS_ENCRYPTED, 1);
- string filename;
- int pwd_type = Get_Password_Type(0, filename);
- if (pwd_type < 0) {
- LOGERR("This TWRP does not have synthetic password decrypt support\n");
- pwd_type = 0; // default password
- }
- DataManager::SetValue(TW_CRYPTO_PWTYPE, pwd_type);
- DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
- DataManager::SetValue("tw_crypto_display", "");
- }
-#else
- LOGERR("FBE found but FBE support not present in TWRP\n");
-#endif
- } else {
- // Filesystem is not encrypted and the mount succeeded, so return to
- // the original unmounted state
- UnMount(false);
- }
+ Decrypt_FBE_DE();
}
if (datamedia && (!Is_Encrypted || (Is_Encrypted && Is_Decrypted))) {
Setup_Data_Media();
@@ -711,6 +675,57 @@ void TWPartition::Setup_Data_Partition(bool Display_Error) {
#endif
}
+bool TWPartition::Decrypt_FBE_DE() {
+if (TWFunc::Path_Exists("/data/unencrypted/key/version")) {
+ LOGINFO("File Based Encryption is present\n");
+#ifdef TW_INCLUDE_FBE
+ ExcludeAll(Mount_Point + "/convert_fbe");
+ ExcludeAll(Mount_Point + "/unencrypted");
+ //ExcludeAll(Mount_Point + "/system/users/0"); // we WILL need to retain some of this if multiple users are present or we just need to delete more folders for the extra users somewhere else
+ ExcludeAll(Mount_Point + "/misc/vold/user_keys");
+ //ExcludeAll(Mount_Point + "/system_ce");
+ //ExcludeAll(Mount_Point + "/system_de");
+ //ExcludeAll(Mount_Point + "/misc_ce");
+ //ExcludeAll(Mount_Point + "/misc_de");
+ ExcludeAll(Mount_Point + "/system/gatekeeper.password.key");
+ ExcludeAll(Mount_Point + "/system/gatekeeper.pattern.key");
+ ExcludeAll(Mount_Point + "/system/locksettings.db");
+ //ExcludeAll(Mount_Point + "/system/locksettings.db-shm"); // don't seem to need this one, but the other 2 are needed
+ ExcludeAll(Mount_Point + "/system/locksettings.db-wal");
+ //ExcludeAll(Mount_Point + "/user_de");
+ //ExcludeAll(Mount_Point + "/misc/profiles/cur/0"); // might be important later
+ ExcludeAll(Mount_Point + "/misc/gatekeeper");
+ ExcludeAll(Mount_Point + "/misc/keystore");
+ ExcludeAll(Mount_Point + "/drm/kek.dat");
+ ExcludeAll(Mount_Point + "/system_de/0/spblob"); // contains data needed to decrypt pixel 2
+ int retry_count = 3;
+ while (!Decrypt_DE() && --retry_count)
+ usleep(2000);
+ if (retry_count > 0) {
+ property_set("ro.crypto.state", "encrypted");
+ Is_Encrypted = true;
+ Is_Decrypted = false;
+ Is_FBE = true;
+ DataManager::SetValue(TW_IS_FBE, 1);
+ DataManager::SetValue(TW_IS_ENCRYPTED, 1);
+ string filename;
+ int pwd_type = Get_Password_Type(0, filename);
+ if (pwd_type < 0) {
+ LOGERR("This TWRP does not have synthetic password decrypt support\n");
+ pwd_type = 0; // default password
+ }
+ DataManager::SetValue(TW_CRYPTO_PWTYPE, pwd_type);
+ DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
+ DataManager::SetValue("tw_crypto_display", "");
+ return true;
+ }
+#else
+ LOGERR("FBE found but FBE support not present in TWRP\n");
+#endif
+ }
+ return false;
+}
+
void TWPartition::Setup_Cache_Partition(bool Display_Error __unused) {
if (Mount_Point != "/cache")
return;
@@ -826,12 +841,14 @@ void TWPartition::Apply_TW_Flag(const unsigned flag, const char* str, const bool
// fileencryption=ice:aes-256-heh
{
std::string FBE = str;
- std::string FBE_contents, FBE_filenames;
size_t colon_loc = FBE.find(":");
if (colon_loc == std::string::npos) {
- LOGINFO("Invalid fileencryption fstab flag: '%s'\n", str);
+ property_set("fbe.contents", FBE.c_str());
+ property_set("fbe.filenames", "");
+ LOGINFO("FBE contents '%s', filenames ''\n", FBE.c_str());
break;
}
+ std::string FBE_contents, FBE_filenames;
FBE_contents = FBE.substr(0, colon_loc);
FBE_filenames = FBE.substr(colon_loc + 1);
property_set("fbe.contents", FBE_contents.c_str());
@@ -905,6 +922,8 @@ void TWPartition::Apply_TW_Flag(const unsigned flag, const char* str, const bool
case TWFLAG_ALTDEVICE:
Alternate_Block_Device = str;
break;
+ case TWFLAG_KEYDIRECTORY:
+ Key_Directory = str;
default:
// Should not get here
LOGINFO("Flag identified for processing, but later unmatched: %i\n", flag);
@@ -1008,6 +1027,7 @@ bool TWPartition::Is_File_System(string File_System) {
File_System == "yaffs2" ||
File_System == "exfat" ||
File_System == "f2fs" ||
+ File_System == "squashfs" ||
File_System == "auto")
return true;
else
@@ -1504,7 +1524,7 @@ bool TWPartition::UnMount(bool Display_Error) {
int never_unmount_system;
DataManager::GetValue(TW_DONT_UNMOUNT_SYSTEM, never_unmount_system);
- if (never_unmount_system == 1 && Mount_Point == "/system")
+ if (never_unmount_system == 1 && Mount_Point == PartitionManager.Get_Android_Root_Path())
return true; // Never unmount system if you're not supposed to unmount it
if (Is_Storage && MTP_Storage_ID > 0)
@@ -1904,21 +1924,26 @@ bool TWPartition::Decrypt(string Password) {
bool TWPartition::Wipe_Encryption() {
bool Save_Data_Media = Has_Data_Media;
+ bool ret = false;
+ BasePartition* base_partition = make_partition();
+
+ if (!base_partition->PreWipeEncryption())
+ goto exit;
if (!UnMount(true))
- return false;
+ goto exit;
Has_Data_Media = false;
- Decrypted_Block_Device = "";
#ifdef TW_INCLUDE_CRYPTO
if (Is_Decrypted && !Decrypted_Block_Device.empty()) {
if (!UnMount(true))
- return false;
+ goto exit;
if (delete_crypto_blk_dev((char*)("userdata")) != 0) {
LOGERR("Error deleting crypto block device, continuing anyway.\n");
}
}
#endif
+ Decrypted_Block_Device = "";
Is_Decrypted = false;
Is_Encrypted = false;
Find_Actual_Block_Device();
@@ -1978,15 +2003,22 @@ bool TWPartition::Wipe_Encryption() {
#ifndef TW_OEM_BUILD
gui_msg("format_data_msg=You may need to reboot recovery to be able to use /data again.");
#endif
- return true;
+ ret = true;
+ if (!Key_Directory.empty())
+ ret = PartitionManager.Wipe_By_Path(Key_Directory);
+ if (ret)
+ ret = base_partition->PostWipeEncryption();
+ goto exit;
} else {
Has_Data_Media = Save_Data_Media;
gui_err("format_data_err=Unable to format to remove encryption.");
if (Has_Data_Media && Mount(false))
PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
- return false;
+ goto exit;
}
- return false;
+exit:
+ delete base_partition;
+ return ret;
}
void TWPartition::Check_FS_Type() {
@@ -2233,18 +2265,23 @@ bool TWPartition::Wipe_F2FS() {
gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkfs.f2fs"));
Find_Actual_Block_Device();
- command = "mkfs.f2fs -t 0";
- if (!Is_Decrypted && Length != 0) {
- // Only use length if we're not decrypted
- char len[32];
- int mod_length = Length;
- if (Length < 0)
- mod_length *= -1;
- sprintf(len, "%i", mod_length);
- command += " -r ";
- command += len;
- }
- command += " " + Actual_Block_Device;
+ if (!TWFunc::Path_Exists("/sbin/sload.f2fs")) {
+ command = "mkfs.f2fs -t 0";
+ if (!Is_Decrypted && Length != 0) {
+ // Only use length if we're not decrypted
+ char len[32];
+ int mod_length = Length;
+ if (Length < 0)
+ mod_length *= -1;
+ sprintf(len, "%i", mod_length);
+ command += " -r ";
+ command += len;
+ }
+ command += " " + Actual_Block_Device;
+ } else {
+ unsigned long long size = IOCTL_Get_Block_Size() + Length;
+ command = "mkfs.f2fs -d1 -f -O encrypt -O quota -O verity -w 4096 " + Actual_Block_Device + " " + std::to_string(size / 4096) + " && sload.f2fs -t /data " + Actual_Block_Device;
+ }
if (TWFunc::Exec_Cmd(command) == 0) {
Recreate_AndSec_Folder();
gui_msg("done=Done.");
@@ -2624,7 +2661,7 @@ bool TWPartition::Restore_Tar(PartitionSettings *part_settings) {
ret = true;
#ifdef HAVE_CAPABILITIES
// Restore capabilities to the run-as binary
- if (Mount_Point == "/system" && Mount(true) && TWFunc::Path_Exists("/system/bin/run-as")) {
+ if (Mount_Point == PartitionManager.Get_Android_Root_Path() && Mount(true) && TWFunc::Path_Exists("/system/bin/run-as")) {
struct vfs_cap_data cap_data;
uint64_t capabilities = (1 << CAP_SETUID) | (1 << CAP_SETGID);
@@ -3009,7 +3046,9 @@ int TWPartition::Check_Lifetime_Writes() {
Mount_Read_Only = true;
if (Mount(false)) {
Find_Actual_Block_Device();
- string block = basename(Actual_Block_Device.c_str());
+ string temp = Actual_Block_Device;
+ Find_Real_Block_Device(temp, false);
+ string block = basename(temp.c_str());
string file = "/sys/fs/" + Current_File_System + "/" + block + "/lifetime_write_kbytes";
string result;
if (TWFunc::Path_Exists(file)) {
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index 5c8a43732..45460d1dc 100644
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -71,6 +71,9 @@ extern "C" {
#include "gui/pages.hpp"
#ifdef TW_INCLUDE_FBE
#include "crypto/ext4crypt/Decrypt.h"
+ #ifdef TW_INCLUDE_FBE_METADATA_DECRYPT
+ #include "crypto/ext4crypt/MetadataCrypt.h"
+ #endif
#endif
#ifdef TW_CRYPTO_USE_SYSTEM_VOLD
#include "crypto/vold_decrypt/vold_decrypt.h"
@@ -277,6 +280,27 @@ int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error)
#ifdef TW_INCLUDE_CRYPTO
TWPartition* Decrypt_Data = Find_Partition_By_Path("/data");
if (Decrypt_Data && Decrypt_Data->Is_Encrypted && !Decrypt_Data->Is_Decrypted) {
+ if (!Decrypt_Data->Key_Directory.empty() && Mount_By_Path(Decrypt_Data->Key_Directory, false)) {
+#ifdef TW_INCLUDE_FBE_METADATA_DECRYPT
+ if (e4crypt_mount_metadata_encrypted(Decrypt_Data->Mount_Point, false, Decrypt_Data->Key_Directory, Decrypt_Data->Actual_Block_Device, &Decrypt_Data->Decrypted_Block_Device)) {
+ LOGINFO("Successfully decrypted metadata encrypted data partition with new block device: '%s'\n", Decrypt_Data->Decrypted_Block_Device.c_str());
+ property_set("ro.crypto.state", "encrypted");
+ Decrypt_Data->Is_Decrypted = true; // Needed to make the mount function work correctly
+ int retry_count = 10;
+ while (!Decrypt_Data->Mount(false) && --retry_count)
+ usleep(500);
+ if (Decrypt_Data->Mount(false)) {
+ Decrypt_Data->Decrypt_FBE_DE();
+ } else {
+ LOGINFO("Failed to mount data after metadata decrypt\n");
+ }
+ } else {
+ LOGINFO("Unable to decrypt metadata encryption\n");
+ }
+#else
+ LOGERR("Metadata FBE decrypt support not present in this TWRP\n");
+#endif
+ }
if (Decrypt_Data->Is_FBE) {
if (DataManager::GetIntValue(TW_CRYPTO_PWTYPE) == 0) {
if (Decrypt_Device("!") == 0) {
@@ -467,6 +491,8 @@ void TWPartitionManager::Output_Partition(TWPartition* Part) {
printf(" Mount_Flags: %i, Mount_Options: %s\n", Part->Mount_Flags, Part->Mount_Options.c_str());
if (Part->MTP_Storage_ID)
printf(" MTP_Storage_ID: %i\n", Part->MTP_Storage_ID);
+ if (!Part->Key_Directory.empty())
+ printf(" Metadata Key Directory: %s\n", Part->Key_Directory.c_str());
printf("\n");
}
@@ -1104,7 +1130,7 @@ int TWPartitionManager::Run_Restore(const string& Restore_Name) {
}
}
TWFunc::GUI_Operation_Text(TW_UPDATE_SYSTEM_DETAILS_TEXT, gui_parse_text("{@updating_system_details}"));
- UnMount_By_Path("/system", false);
+ UnMount_By_Path(Get_Android_Root_Path(), false);
Update_System_Details();
UnMount_Main_Partitions();
time(&rStop);
@@ -1490,7 +1516,7 @@ void TWPartitionManager::Update_System_Details(void) {
for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
(*iter)->Update_Size(true);
if ((*iter)->Can_Be_Mounted) {
- if ((*iter)->Mount_Point == "/system") {
+ if ((*iter)->Mount_Point == Get_Android_Root_Path()) {
int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
DataManager::SetValue(TW_BACKUP_SYSTEM_SIZE, backup_display_size);
} else if ((*iter)->Mount_Point == "/data" || (*iter)->Mount_Point == "/datadata") {
@@ -1859,7 +1885,7 @@ void TWPartitionManager::UnMount_Main_Partitions(void) {
TWPartition* Boot_Partition = Find_Partition_By_Path("/boot");
- UnMount_By_Path("/system", true);
+ UnMount_By_Path(Get_Android_Root_Path(), true);
if (!datamedia)
UnMount_By_Path("/data", true);
@@ -2726,6 +2752,13 @@ string TWPartitionManager::Get_Active_Slot_Display() {
return Active_Slot_Display;
}
+string TWPartitionManager::Get_Android_Root_Path() {
+ std::string Android_Root = getenv("ANDROID_ROOT");
+ if (Android_Root == "")
+ Android_Root = "/system";
+ return Android_Root;
+}
+
void TWPartitionManager::Remove_Uevent_Devices(const string& Mount_Point) {
std::vector<TWPartition*>::iterator iter;
diff --git a/partitions.hpp b/partitions.hpp
index d780fe560..a8fd70b40 100644
--- a/partitions.hpp
+++ b/partitions.hpp
@@ -31,6 +31,23 @@
using namespace std;
+// BasePartition is used for overriding so we can run custom, device
+// specific code.
+class BasePartition {
+ public:
+ explicit BasePartition() {}
+ virtual ~BasePartition() {}
+
+ virtual bool PreWipeEncryption() {
+ return true;
+ }
+
+ virtual bool PostWipeEncryption() {
+ return true;
+ }
+};
+BasePartition* make_partition();
+
struct PartitionList {
std::string Display_Name;
std::string Mount_Point;
@@ -128,6 +145,7 @@ public:
void Partition_Post_Processing(bool Display_Error); // Apply partition specific settings after fstab processed
void Set_Backup_FileName(string fname); // Set Backup_FileName for partition
string Get_Backup_Name(); // Get Backup_Name for partition
+ bool Decrypt_FBE_DE(); // If FBE is present, backup exclusions are set up and DE decrypt is attempted
public:
string Current_File_System; // Current file system
@@ -246,6 +264,7 @@ private:
bool SlotSelect; // Partition has A/B slots
TWExclude backup_exclusions; // Exclusions for file based backups
TWExclude wipe_exclusions; // Exclusions for file based wipes (data/media devices only)
+ string Key_Directory; // Metadata key directory needed for mounting FBE encrypted data partitions using metadata encryption
struct partition_fs_flags_struct { // This struct is used to store mount flags and options for different file systems for the same partition
string File_System;
@@ -332,6 +351,7 @@ public:
void Set_Active_Slot(const string& Slot); // Sets the active slot to A or B
string Get_Active_Slot_Suffix(); // Returns active slot _a or _b
string Get_Active_Slot_Display(); // Returns active slot A or B for display purposes
+ string Get_Android_Root_Path(); // Returns path of ANDROID_ROOT environment variable
struct pollfd uevent_pfd; // Used for uevent code
void Remove_Uevent_Devices(const string& sysfs_path); // Removes subpartitions from the Partitions vector for a matched uevent device
void Handle_Uevent(const Uevent_Block_Data& uevent_data); // Handle uevent data
diff --git a/prebuilt/Android.mk b/prebuilt/Android.mk
index 8471ffba1..5dc110e91 100644
--- a/prebuilt/Android.mk
+++ b/prebuilt/Android.mk
@@ -16,19 +16,22 @@ RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/flash_image
RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/erase_image
RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/bu
ifneq ($(TW_USE_TOOLBOX), true)
- RELINK_SOURCE_FILES += $(TARGET_OUT_OPTIONAL_EXECUTABLES)/busybox
+ RELINK_SOURCE_FILES += $(TARGET_OUT_OPTIONAL_EXECUTABLES)/busybox
else
- RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/sh
- RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libcrypto.so
- ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 23; echo $$?),0)
- RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/toybox
- ifneq ($(wildcard external/zip/Android.mk),)
- RELINK_SOURCE_FILES += $(TARGET_OUT_OPTIONAL_EXECUTABLES)/zip
- endif
- ifneq ($(wildcard external/unzip/Android.mk),)
- RELINK_SOURCE_FILES += $(TARGET_OUT_OPTIONAL_EXECUTABLES)/unzip
- endif
- endif
+ RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/sh
+ RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libcrypto.so
+ ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 23; echo $$?),0)
+ RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/toybox
+ ifneq ($(wildcard external/zip/Android.mk),)
+ RELINK_SOURCE_FILES += $(TARGET_OUT_OPTIONAL_EXECUTABLES)/zip
+ endif
+ ifneq ($(wildcard external/unzip/Android.mk),)
+ RELINK_SOURCE_FILES += $(TARGET_OUT_OPTIONAL_EXECUTABLES)/unzip
+ endif
+ ifneq ($(wildcard system/core/libziparchive/Android.bp),)
+ RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/unzip
+ endif
+ endif
endif
RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/pigz
RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/fsck.fat
@@ -63,6 +66,9 @@ RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext2_e2p.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext2fs.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext2_profile.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext2_uuid.so
+ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 27; echo $$?),0)
+ RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext2_misc.so
+endif
ifneq ($(wildcard external/e2fsprogs/lib/quota/Android.mk),)
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext2_quota.so
endif
@@ -205,6 +211,9 @@ ifeq ($(TW_INCLUDE_CRYPTO), true)
ifneq ($(wildcard hardware/interfaces/weaver/Android.bp),)
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.weaver@1.0.so
endif
+ ifneq ($(wildcard hardware/interfaces/weaver/1.0/Android.bp),)
+ RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.weaver@1.0.so
+ endif
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libhardware_legacy.so
else
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeymaster1.so
@@ -223,6 +232,11 @@ ifeq ($(TW_INCLUDE_CRYPTO), true)
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libservices.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeymaster_portable.so
endif
+ # lshal can be useful for seeing if you have things like the keymaster working properly, but it isn't needed for TWRP to work
+ #RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/lshal
+ #RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/liblshal.so
+ #RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libssl.so
+ #RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libhidl-gen-hash.so
endif
endif
ifeq ($(AB_OTA_UPDATER), true)
@@ -249,6 +263,9 @@ ifeq ($(TARGET_USERIMAGES_USE_F2FS), true)
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libf2fs.so
else ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26; echo $$?),0)
RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/mkfs.f2fs
+ ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 28; echo $$?),0)
+ RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/sload.f2fs
+ endif
else ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 24; echo $$?),0)
RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/mkfs.f2fs
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libf2fs.so
@@ -331,6 +348,7 @@ endif
ifeq ($(shell test $(PLATFORM_SDK_VERSION) -gt 27; echo $$?),0)
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libclang_rt.ubsan_standalone-aarch64-android.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/liblogwrap.so
+ RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext2_misc.so
endif
TW_BB_SYMLINKS :=
@@ -473,6 +491,18 @@ ifeq ($(TW_INCLUDE_DUMLOCK), true)
include $(BUILD_PREBUILT)
endif
+ifeq ($(TW_USE_TOOLBOX), true)
+ include $(CLEAR_VARS)
+ LOCAL_MODULE := mkshrc_twrp
+ LOCAL_MODULE_TAGS := eng
+ LOCAL_MODULE_CLASS := ETC
+ LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/etc
+ LOCAL_SRC_FILES := $(LOCAL_MODULE)
+ LOCAL_POST_INSTALL_CMD := \
+ $(hide) mv $(TARGET_RECOVERY_ROOT_OUT)/etc/mkshrc_twrp $(TARGET_RECOVERY_ROOT_OUT)/etc/mkshrc
+ include $(BUILD_PREBUILT)
+endif
+
#TWRP App "placeholder"
include $(CLEAR_VARS)
LOCAL_MODULE := me.twrp.twrpapp.apk
@@ -481,3 +511,18 @@ LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
+
+ifeq ($(TW_INCLUDE_CRYPTO), true)
+ ifneq ($(TW_CRYPTO_USE_SYSTEM_VOLD),)
+ ifneq ($(shell test $(PLATFORM_SDK_VERSION) -ge 28; echo $$?),0)
+ # Prebuilt vdc_pie for pre-Pie SDK Platforms
+ include $(CLEAR_VARS)
+ LOCAL_MODULE := vdc_pie
+ LOCAL_MODULE_TAGS := eng
+ LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
+ LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
+ LOCAL_SRC_FILES := vdc_pie-$(TARGET_ARCH)
+ include $(BUILD_PREBUILT)
+ endif
+ endif
+endif
diff --git a/prebuilt/mkshrc_twrp b/prebuilt/mkshrc_twrp
new file mode 100755
index 000000000..c103d6c56
--- /dev/null
+++ b/prebuilt/mkshrc_twrp
@@ -0,0 +1,21 @@
+# Copyright (c) 2010, 2012, 2013, 2014
+# Thorsten Glaser <tg@mirbsd.org>
+# This file is provided under the same terms as mksh.
+#-
+# Minimal /system/etc/mkshrc for Android
+#
+# Support: https://launchpad.net/mksh
+
+: ${HOSTNAME:=$(getprop ro.product.device)}
+: ${HOSTNAME:=android}
+: ${TMPDIR:=/tmp}
+export HOSTNAME TMPDIR
+
+if (( USER_ID )); then PS1='$'; else PS1='#'; fi
+PS4='[$EPOCHREALTIME] '; PS1='${|
+ local e=$?
+
+ (( e )) && REPLY+="$e|"
+
+ return $e
+}$HOSTNAME:${PWD:-?} '"$PS1 "
diff --git a/prebuilt/vdc_pie-arm b/prebuilt/vdc_pie-arm
new file mode 100755
index 000000000..cf05cad53
--- /dev/null
+++ b/prebuilt/vdc_pie-arm
Binary files differ
diff --git a/prebuilt/vdc_pie-arm64 b/prebuilt/vdc_pie-arm64
new file mode 100755
index 000000000..46231402f
--- /dev/null
+++ b/prebuilt/vdc_pie-arm64
Binary files differ
diff --git a/toybox/Android.mk b/toybox/Android.mk
index 5b2f32fd7..c88f360f5 100644
--- a/toybox/Android.mk
+++ b/toybox/Android.mk
@@ -532,7 +532,7 @@ ALL_TOOLS += \
vconfig \
watch \
xxd
-ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 27; echo $$?),0)
+ifeq ($(shell test $(PLATFORM_SDK_VERSION) -le 27; echo $$?),0)
ALL_TOOLS += \
getprop \
xzcat
diff --git a/twrp-functions.cpp b/twrp-functions.cpp
index 40205c943..00a57a749 100644
--- a/twrp-functions.cpp
+++ b/twrp-functions.cpp
@@ -407,7 +407,7 @@ string TWFunc::Get_Root_Path(const string& Path) {
void TWFunc::install_htc_dumlock(void) {
int need_libs = 0;
- if (!PartitionManager.Mount_By_Path("/system", true))
+ if (!PartitionManager.Mount_By_Path(PartitionManager.Get_Android_Root_Path(), true))
return;
if (!PartitionManager.Mount_By_Path("/data", true))
@@ -809,19 +809,19 @@ string TWFunc::Get_Current_Date() {
}
string TWFunc::System_Property_Get(string Prop_Name) {
- bool mount_state = PartitionManager.Is_Mounted_By_Path("/system");
+ bool mount_state = PartitionManager.Is_Mounted_By_Path(PartitionManager.Get_Android_Root_Path());
std::vector<string> buildprop;
string propvalue;
- if (!PartitionManager.Mount_By_Path("/system", true))
+ if (!PartitionManager.Mount_By_Path(PartitionManager.Get_Android_Root_Path(), true))
return propvalue;
string prop_file = "/system/build.prop";
if (!TWFunc::Path_Exists(prop_file))
- prop_file = "/system/system/build.prop"; // for devices with system as a root file system (e.g. Pixel)
+ prop_file = PartitionManager.Get_Android_Root_Path() + "/system/build.prop"; // for devices with system as a root file system (e.g. Pixel)
if (TWFunc::read_file(prop_file, buildprop) != 0) {
- LOGINFO("Unable to open /system/build.prop for getting '%s'.\n", Prop_Name.c_str());
+ LOGINFO("Unable to open build.prop for getting '%s'.\n", Prop_Name.c_str());
DataManager::SetValue(TW_BACKUP_NAME, Get_Current_Date());
if (!mount_state)
- PartitionManager.UnMount_By_Path("/system", false);
+ PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), false);
return propvalue;
}
int line_count = buildprop.size();
@@ -834,12 +834,12 @@ string TWFunc::System_Property_Get(string Prop_Name) {
if (propname == Prop_Name) {
propvalue = buildprop.at(index).substr(end_pos + 1, buildprop.at(index).size());
if (!mount_state)
- PartitionManager.UnMount_By_Path("/system", false);
+ PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), false);
return propvalue;
}
}
if (!mount_state)
- PartitionManager.UnMount_By_Path("/system", false);
+ PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), false);
return propvalue;
}
@@ -922,7 +922,7 @@ void TWFunc::Fixup_Time_On_Boot(const string& time_paths /* = "" */)
std::vector<std::string> paths; // space separated list of paths
if (time_paths.empty()) {
- paths = Split_String("/data/system/time/ /data/time/", " ");
+ paths = Split_String("/data/system/time/ /data/time/ /data/vendor/time/", " ");
if (!PartitionManager.Mount_By_Path("/data", false))
return;
} else {
@@ -1095,14 +1095,14 @@ std::string TWFunc::to_string(unsigned long value) {
}
void TWFunc::Disable_Stock_Recovery_Replace(void) {
- if (PartitionManager.Mount_By_Path("/system", false)) {
+ if (PartitionManager.Mount_By_Path(PartitionManager.Get_Android_Root_Path(), false)) {
// Disable flashing of stock recovery
if (TWFunc::Path_Exists("/system/recovery-from-boot.p")) {
rename("/system/recovery-from-boot.p", "/system/recovery-from-boot.bak");
gui_msg("rename_stock=Renamed stock recovery file in /system to prevent the stock ROM from replacing TWRP.");
sync();
}
- PartitionManager.UnMount_By_Path("/system", false);
+ PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), false);
}
}
diff --git a/twrp.cpp b/twrp.cpp
index 3102efdc0..2399c0bb3 100644
--- a/twrp.cpp
+++ b/twrp.cpp
@@ -333,7 +333,7 @@ int main(int argc, char **argv) {
#ifndef TW_OEM_BUILD
// Check if system has never been changed
- TWPartition* sys = PartitionManager.Find_Partition_By_Path("/system");
+ TWPartition* sys = PartitionManager.Find_Partition_By_Path(PartitionManager.Get_Android_Root_Path());
TWPartition* ven = PartitionManager.Find_Partition_By_Path("/vendor");
if (sys) {
diff --git a/twrpAdbBuFifo.cpp b/twrpAdbBuFifo.cpp
index f98eb0556..22bfa4054 100644
--- a/twrpAdbBuFifo.cpp
+++ b/twrpAdbBuFifo.cpp
@@ -309,7 +309,7 @@ bool twrpAdbBuFifo::Restore_ADB_Backup(void) {
part_settings.Part->Set_Backup_FileName(Backup_FileName);
PartitionManager.Set_Restore_Files(path);
- if (path.compare("/system") == 0) {
+ if (path.compare(PartitionManager.Get_Android_Root_Path()) == 0) {
if (part_settings.Part->Is_Read_Only()) {
if (!twadbbu::Write_TWERROR())
LOGERR("Unable to write to TWRP ADB Backup.\n");
diff --git a/updater/install.cpp b/updater/install.cpp
index 741d97014..2266127f2 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -97,6 +97,34 @@ static void uiPrint(State* state, const std::string& buffer) {
LOG(INFO) << buffer;
}
+static bool is_dir(const std::string& dirpath) {
+ struct stat st;
+ return stat(dirpath.c_str(), &st) == 0 && S_ISDIR(st.st_mode);
+}
+
+// Create all parent directories of name, if necessary.
+static bool make_parents(const std::string& name) {
+ size_t prev_end = 0;
+ while (prev_end < name.size()) {
+ size_t next_end = name.find('/', prev_end + 1);
+ if (next_end == std::string::npos) {
+ break;
+ }
+ std::string dir_path = name.substr(0, next_end);
+ if (!is_dir(dir_path)) {
+ int result = mkdir(dir_path.c_str(), 0700);
+ if (result != 0) {
+ PLOG(ERROR) << "failed to mkdir " << dir_path << " when make parents for " << name;
+ return false;
+ }
+
+ LOG(INFO) << "created [" << dir_path << "]";
+ }
+ prev_end = next_end;
+ }
+ return true;
+}
+
void uiPrintf(State* _Nonnull state, const char* _Nonnull format, ...) {
std::string error_msg;