diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000000..39bbd2681d --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,4 @@ +{ + "image": "mcr.microsoft.com/devcontainers/universal:2", + "features": {} +} diff --git a/.gitignore b/.gitignore index e03babb1f6..480f5478d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .*.swp *~ tags +.vscode diff --git a/Android.mk b/Android.mk index d0d962f54c..ccfa5d876b 100755 --- a/Android.mk +++ b/Android.mk @@ -75,7 +75,24 @@ LOCAL_SRC_FILES := \ twrpDigestDriver.cpp \ openrecoveryscript.cpp \ tarWrite.c \ - twrpAdbBuFifo.cpp + twrpAdbBuFifo.cpp \ + twrpRepacker.cpp + +ifeq ($(TW_AMONET), true) + LOCAL_SRC_FILES += amonet.cpp + ifneq ($(TW_AMONET_MICROLOADER_SRC),) + LOCAL_SRC_FILES += ../../$(TW_AMONET_MICROLOADER_SRC) + LOCAL_CFLAGS += -DTW_MICROLOADER + endif +endif + +ifeq ($(TW_IP_ADDRESS), true) + LOCAL_CFLAGS += -DTW_IP_ADDRESS +endif + +ifeq ($(TW_IP_SIDELOAD), true) + LOCAL_CFLAGS += -DTW_IP_SIDELOAD +endif ifneq ($(TARGET_RECOVERY_REBOOT_SRC),) LOCAL_SRC_FILES += $(TARGET_RECOVERY_REBOOT_SRC) @@ -143,6 +160,10 @@ ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 23; echo $$?),0) LOCAL_SHARED_LIBRARIES += libstlport LOCAL_CFLAGS += -DTW_NO_SHA2_LIBRARY endif +LOCAL_CFLAGS += -DSDK_VERSION=$(PLATFORM_SDK_VERSION) +ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 25; echo $$?),0) + LOCAL_CFLAGS += -DUSE_OLD_BASE_INCLUDE +endif ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 24; echo $$?),0) LOCAL_SHARED_LIBRARIES += libmincrypttwrp LOCAL_C_INCLUDES += $(LOCAL_PATH)/libmincrypt/includes @@ -151,7 +172,7 @@ else LOCAL_SHARED_LIBRARIES += libcrypto endif -ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 24; echo $$?),0) +ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 23; echo $$?),0) LOCAL_SHARED_LIBRARIES += libbase endif @@ -172,12 +193,17 @@ ifeq ($(TW_OEM_BUILD),true) BOARD_HAS_NO_REAL_SDCARD := true TW_USE_TOOLBOX := true TW_EXCLUDE_MTP := true + TW_EXCLUDE_TZDATA := true + TW_EXCLUDE_NANO := true + TW_EXCLUDE_BASH := true endif ifeq ($(TARGET_USERIMAGES_USE_EXT4), true) ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 28; echo $$?),0) LOCAL_CFLAGS += -DUSE_EXT4 - LOCAL_C_INCLUDES += system/extras/ext4_utils + LOCAL_C_INCLUDES += system/extras/ext4_utils \ + system/extras/ext4_utils/include \ + $(commands_TWRP_local_path)/crypto/ext4crypt LOCAL_SHARED_LIBRARIES += libext4_utils ifneq ($(wildcard external/lz4/Android.mk),) #LOCAL_STATIC_LIBRARIES += liblz4 @@ -193,6 +219,10 @@ ifeq ($(AB_OTA_UPDATER),true) TWRP_REQUIRED_MODULES += libhardware endif +ifneq ($(TW_SYSTEM_BUILD_PROP_ADDITIONAL_PATHS),) + LOCAL_CFLAGS += -DTW_SYSTEM_BUILD_PROP_ADDITIONAL_PATHS='"$(TW_SYSTEM_BUILD_PROP_ADDITIONAL_PATHS)"' +endif + LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin #ifeq ($(TARGET_RECOVERY_UI_LIB),) @@ -206,8 +236,6 @@ else LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_TWRP_LIB) endif -LOCAL_C_INCLUDES += system/extras/ext4_utils - tw_git_revision := $(shell git -C $(LOCAL_PATH) rev-parse --short=8 HEAD 2>/dev/null) ifeq ($(shell git -C $(LOCAL_PATH) diff --quiet; echo $$?),1) tw_git_revision := $(tw_git_revision)-dirty @@ -215,6 +243,11 @@ endif LOCAL_CFLAGS += -DTW_GIT_REVISION='"$(tw_git_revision)"' ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 28; echo $$?),0) +ifeq ($(TW_FORCE_USE_BUSYBOX), true) + TW_USE_TOOLBOX := false +else + TW_USE_TOOLBOX := true +endif ifeq ($(TW_EXCLUDE_MTP),) LOCAL_SHARED_LIBRARIES += libtwrpmtp-ffs endif @@ -225,6 +258,13 @@ ifeq ($(TW_EXCLUDE_MTP),) endif endif +ifeq ($(BOARD_USES_RECOVERY_AS_BOOT), true) + LOCAL_CFLAGS += -DBOARD_USES_RECOVERY_AS_BOOT +endif +ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE), true) + LOCAL_CFLAGS += -DBOARD_BUILD_SYSTEM_ROOT_IMAGE +endif + #TWRP Build Flags ifeq ($(TW_EXCLUDE_MTP),) LOCAL_CFLAGS += -DTW_HAS_MTP @@ -232,6 +272,9 @@ endif ifneq ($(TW_NO_SCREEN_TIMEOUT),) LOCAL_CFLAGS += -DTW_NO_SCREEN_TIMEOUT endif +ifneq ($(TW_NO_SCREEN),) + LOCAL_CFLAGS += -DTW_NO_SCREEN +endif ifeq ($(BOARD_HAS_NO_REAL_SDCARD), true) LOCAL_CFLAGS += -DBOARD_HAS_NO_REAL_SDCARD endif @@ -259,6 +302,15 @@ endif ifeq ($(TW_NO_REBOOT_BOOTLOADER), true) LOCAL_CFLAGS += -DTW_NO_REBOOT_BOOTLOADER endif +ifeq ($(TW_AMONET), true) + LOCAL_CFLAGS += -DTW_AMONET +endif +ifeq ($(TW_HACKED_BL_BUTTON), true) + LOCAL_CFLAGS += -DTW_HACKED_BL_BUTTON +endif +ifeq ($(TW_BOOT_MENU), true) + LOCAL_CFLAGS += -DTW_BOOT_MENU +endif ifeq ($(TW_NO_REBOOT_RECOVERY), true) LOCAL_CFLAGS += -DTW_NO_REBOOT_RECOVERY endif @@ -333,6 +385,9 @@ ifeq ($(TW_INCLUDE_CRYPTO), true) endif ifneq ($(TW_CRYPTO_USE_SYSTEM_VOLD),) ifneq ($(TW_CRYPTO_USE_SYSTEM_VOLD),false) + ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26; echo $$?),0) + TW_INCLUDE_LIBRESETPROP := true + endif LOCAL_CFLAGS += -DTW_CRYPTO_USE_SYSTEM_VOLD LOCAL_STATIC_LIBRARIES += libvolddecrypt endif @@ -395,9 +450,32 @@ ifneq ($(TW_DEFAULT_LANGUAGE),) else LOCAL_CFLAGS += -DTW_DEFAULT_LANGUAGE=en endif +ifneq ($(TW_QCOM_ATS_OFFSET),) + LOCAL_CFLAGS += -DTW_QCOM_ATS_OFFSET=$(TW_QCOM_ATS_OFFSET) +endif ifneq ($(TW_CLOCK_OFFSET),) LOCAL_CFLAGS += -DTW_CLOCK_OFFSET=$(TW_CLOCK_OFFSET) endif +ifneq ($(TW_OVERRIDE_SYSTEM_PROPS),) + TW_INCLUDE_LIBRESETPROP := true + LOCAL_CFLAGS += -DTW_OVERRIDE_SYSTEM_PROPS=$(TW_OVERRIDE_SYSTEM_PROPS) +endif +ifneq ($(TW_INCLUDE_LIBRESETPROP),) + ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 24; echo $$?),0) + $(warning libresetprop is not available for android < 7) + else + LOCAL_SHARED_LIBRARIES += libresetprop + LOCAL_C_INCLUDES += external/magisk-prebuilt/include + LOCAL_CFLAGS += -DTW_INCLUDE_LIBRESETPROP + endif +endif +ifeq ($(TW_EXCLUDE_NANO), true) + LOCAL_CFLAGS += -DTW_EXCLUDE_NANO +endif +ifneq ($(TW_DEFAULT_BACKUP_LIST),) + LOCAL_CFLAGS += -DTW_DEFAULT_BACKUP_LIST=$(TW_DEFAULT_BACKUP_LIST) +endif + TWRP_REQUIRED_MODULES += \ dump_image \ erase_image \ @@ -427,9 +505,9 @@ else endif ifneq ($(TW_USE_TOOLBOX), true) ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 24; echo $$?),0) - LOCAL_POST_INSTALL_CMD := \ - $(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/sbin && \ - ln -sf /sbin/busybox $(TARGET_RECOVERY_ROOT_OUT)/sbin/sh + LOCAL_POST_INSTALL_CMD += \ + $(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/sbin; \ + ln -sf /sbin/busybox $(TARGET_RECOVERY_ROOT_OUT)/sbin/sh; endif else ifneq ($(wildcard external/toybox/Android.mk),) @@ -483,6 +561,32 @@ ifeq ($(TWRP_INCLUDE_LOGCAT), true) TWRP_REQUIRED_MODULES += logcat ifeq ($(TARGET_USES_LOGD), true) TWRP_REQUIRED_MODULES += logd libsysutils libnl init.recovery.logd.rc + ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 28; echo $$?),0) + TWRP_REQUIRED_MODULES += event-log-tags + ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true) + LOCAL_POST_INSTALL_CMD += \ + mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/system_root/system/etc; \ + cp -f $(TARGET_OUT_ETC)/event-log-tags $(TARGET_RECOVERY_ROOT_OUT)/system_root/system/etc/; + else + LOCAL_POST_INSTALL_CMD += \ + mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/system/etc; \ + cp -f $(TARGET_OUT_ETC)/event-log-tags $(TARGET_RECOVERY_ROOT_OUT)/system/etc/; + endif + endif + endif +endif +ifneq ($(TW_EXCLUDE_TZDATA), true) + TWRP_REQUIRED_MODULES += tzdata_twrp +endif +ifneq ($(TW_EXCLUDE_NANO), true) + TWRP_REQUIRED_MODULES += \ + nano_twrp \ + init.recovery.nano.rc +endif +ifneq ($(TW_EXCLUDE_BASH), true) + ifneq ($(wildcard external/bash/.),) + TWRP_REQUIRED_MODULES += \ + bash_twrp endif endif # Allow devices to specify device-specific recovery dependencies @@ -517,15 +621,10 @@ endif ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26; echo $$?),0) TWRP_REQUIRED_MODULES += ld.config.txt - ifeq ($(BOARD_VNDK_RUNTIME_DISABLE),true) - LOCAL_POST_INSTALL_CMD += \ - sed '0,/^namespace.default.search.paths\s\{1,\}/!b;//a\namespace.default.search.paths += \/sbin' \ - $(TARGET_OUT_ETC)/ld.config.vndk_lite.txt > $(TARGET_RECOVERY_ROOT_OUT)/sbin/ld.config.txt; - else - LOCAL_POST_INSTALL_CMD += \ - sed '0,/^namespace.default.search.paths\s\{1,\}/!b;//a\namespace.default.search.paths += \/sbin' \ - $(TARGET_OUT_ETC)/ld.config.txt > $(TARGET_RECOVERY_ROOT_OUT)/sbin/ld.config.txt; - endif + TWRP_REQUIRED_MODULES += init.recovery.ldconfig.rc + LOCAL_POST_INSTALL_CMD += \ + sed 's/\(namespace.default.search.paths\)\s\{1,\}=/namespace.default.search.paths = \/sbin\n\1 +=/' \ + $(TARGET_OUT_ETC)/ld.config*.txt > $(TARGET_RECOVERY_ROOT_OUT)/sbin/ld.config.txt; endif ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 25; echo $$?),0) @@ -544,6 +643,12 @@ else LOCAL_ADDITIONAL_DEPENDENCIES += $(TWRP_REQUIRED_MODULES) endif +TW_THEME_VERSION := $(shell grep TW_THEME_VERSION bootable/recovery/variables.h | cut -d ' ' -f 3) + +LOCAL_POST_INSTALL_CMD += \ + sed -i "s/{themeversion}/$(TW_THEME_VERSION)/" $(TARGET_RECOVERY_ROOT_OUT)$(TWRES_PATH)splash.xml; \ + sed -i "s/{themeversion}/$(TW_THEME_VERSION)/" $(TARGET_RECOVERY_ROOT_OUT)$(TWRES_PATH)ui.xml; + include $(BUILD_EXECUTABLE) # Symlink for file_contexts @@ -556,8 +661,8 @@ ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 28; echo $$?),0) else LOCAL_ADDITIONAL_DEPENDENCIES := file_contexts.bin endif -LOCAL_POST_INSTALL_CMD := \ - $(hide) cp -f $(PRODUCT_OUT)/obj/ETC/file_contexts.bin_intermediates/file_contexts.concat.tmp $(TARGET_RECOVERY_ROOT_OUT)/file_contexts +LOCAL_POST_INSTALL_CMD += \ + cp -f $(PRODUCT_OUT)/obj/ETC/file_contexts.bin_intermediates/file_contexts.concat.tmp $(TARGET_RECOVERY_ROOT_OUT)/file_contexts; include $(BUILD_PHONY_PACKAGE) @@ -875,6 +980,11 @@ ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 24; echo $$?),0) include $(commands_TWRP_local_path)/libmincrypt/Android.mk endif +ifneq ($(TW_OZIP_DECRYPT_KEY),) + TWRP_REQUIRED_MODULES += ozip_decrypt + include $(commands_TWRP_local_path)/ozip_decrypt/Android.mk +endif + ifeq ($(TW_INCLUDE_CRYPTO), true) include $(commands_TWRP_local_path)/crypto/fde/Android.mk include $(commands_TWRP_local_path)/crypto/scrypt/Android.mk diff --git a/amonet.cpp b/amonet.cpp new file mode 100644 index 0000000000..298452b07e --- /dev/null +++ b/amonet.cpp @@ -0,0 +1,169 @@ +#ifdef TW_AMONET + +#include + +#include "amonet.h" +#include "microloader.h" +#include "twcommon.h" +#include "partitions.hpp" + +int unpatch_part(const char* part_path) { + FILE *fp = NULL; + uint8_t boot_data[0x800]; + int ret = -1; + + const char *part_name = &part_path[1]; + + TWPartition* partition = PartitionManager.Find_Partition_By_Path(part_path); + const char* amonet_part = partition?partition->Actual_Block_Device.c_str():""; + + gui_print_color("highlight", EXPLOIT_TAG "Remove %s patch...\n", part_name); + + fp = fopen(amonet_part, "r+b"); + if (!fp) { + gui_print_color("highlight", EXPLOIT_TAG "Failed to open the %s device\n", part_name); + goto cleanup; + } + + if (fread(boot_data, sizeof(boot_data), 1, fp) != 1) { + gui_print_color("highlight", EXPLOIT_TAG "Failed to read data\n"); + goto cleanup; + } + + if (memcmp(boot_data + 0x400, "ANDROID!", 8) != 0) { + // Exploit not installed yet, but that's okay + gui_print_color("highlight", EXPLOIT_TAG "NOT_INSTALLED\n"); + ret = 0; + goto cleanup; + } + + // Assume exploit is installed. Uninstall it by copying the second 0x400 over the first 0x400 + memcpy(boot_data, boot_data + 0x400, 0x400); + // and zero out the second 0x400 + memset(boot_data + 0x400, 0, 0x400); + + if (fseek(fp, 0, SEEK_SET) != 0) { + gui_print_color("highlight", EXPLOIT_TAG "Failed to seek\n"); + goto cleanup; + } + + if (fwrite(boot_data, sizeof(boot_data), 1, fp) != 1) { + gui_print_color("highlight", EXPLOIT_TAG "Failed to write data\n"); + goto cleanup; + } + + gui_print_color("highlight", EXPLOIT_TAG "OK\n"); + ret = 0; + +cleanup: + if (fp) { + fclose(fp); + fp = NULL; + } + + return ret; +} + +int patch_part(const char* part_path) { + FILE *fp = NULL; + uint8_t boot_data[0x800]; + int ret = -1; + + const char *part_name = &part_path[1]; + + TWPartition* partition = PartitionManager.Find_Partition_By_Path(part_path); + const char *amonet_part = partition?partition->Actual_Block_Device.c_str():""; + + gui_print_color("highlight", EXPLOIT_TAG "Install %s patch... \n", part_name); + + fp = fopen(amonet_part, "r+b"); + if (!fp) { + gui_print_color("highlight", EXPLOIT_TAG "Failed to open the %s device\n", part_name); + goto cleanup; + } + + if (fread(boot_data, sizeof(boot_data), 1, fp) != 1) { + gui_print_color("highlight", EXPLOIT_TAG "Failed to read data\n"); + goto cleanup; + } + + if (memcmp(boot_data + 0x400, "ANDROID!", 8) == 0) { + gui_print_color("highlight", EXPLOIT_TAG "ALREADY_INSTALLED\n"); // If the rom author injected the boot image herself + ret = 0; + goto cleanup; + } + + // Copy first half to the second half, replace first half with the microloader + memcpy(boot_data + 0x400, boot_data, 0x400); + memcpy(boot_data, microloader_bin, 0x400); + + if (fseek(fp, 0, SEEK_SET) != 0) { + gui_print_color("highlight", EXPLOIT_TAG "Failed to seek\n"); + goto cleanup; + } + + if (fwrite(boot_data, sizeof(boot_data), 1, fp) != 1) { + gui_print_color("highlight", EXPLOIT_TAG "Failed to write data\n"); + goto cleanup; + } + + gui_print_color("highlight", EXPLOIT_TAG "OK\n"); + ret = 0; + +cleanup: + if (fp) { + fclose(fp); + fp = NULL; + } + + return ret; +} + +int load_microloader() { +#ifdef TW_MICROLOADER + return 0; +#else + FILE *fp = NULL; + uint8_t boot_data[0x800]; + int ret = -1; + static const char *part_path = "/recovery"; + + const char *part_name = &part_path[1]; + + TWPartition* partition = PartitionManager.Find_Partition_By_Path(part_path); + const char *amonet_part = partition?partition->Actual_Block_Device.c_str():""; + + gui_print_color("highlight", EXPLOIT_TAG "Load microloader from %s... \n", part_name); + + fp = fopen(amonet_part, "r+b"); + if (!fp) { + gui_print_color("highlight", EXPLOIT_TAG "Failed to open the %s device\n", part_name); + goto cleanup; + } + + if (fread(boot_data, sizeof(boot_data), 1, fp) != 1) { + gui_print_color("highlight", EXPLOIT_TAG "Failed to read data\n"); + goto cleanup; + } + + if (memcmp(boot_data + 0x400, "ANDROID!", 8) != 0) { + gui_print_color("highlight", EXPLOIT_TAG "No microloader found in recovery\n"); + ret = 0; + goto cleanup; + } + + if(memcpy(microloader_bin, boot_data, 0x400)) + ret = 0; + + +cleanup: + if (fp) { + fclose(fp); + fp = NULL; + } + + return ret; +#endif +} + +#endif diff --git a/amonet.h b/amonet.h new file mode 100644 index 0000000000..1798a5c5dd --- /dev/null +++ b/amonet.h @@ -0,0 +1,13 @@ +#ifdef TW_AMONET +#ifndef RECOVERY_AMONET_H_ +#define RECOVERY_AMONET_H_ + +#include + +#define EXPLOIT_TAG "[amonet] " +int patch_part(const char* part_path); +int unpatch_part(const char* part_path); +int load_microloader(void); + +#endif // RECOVERY_AMONET_H_ +#endif // TW_AMONET diff --git a/bootloader_message_twrp/Android.mk b/bootloader_message_twrp/Android.mk index e7a3ea0f8c..932cd040c6 100644 --- a/bootloader_message_twrp/Android.mk +++ b/bootloader_message_twrp/Android.mk @@ -31,5 +31,10 @@ LOCAL_CFLAGS := -Werror -std=c++11 ifeq ($(TW_IGNORE_MISC_WIPE_DATA), true) LOCAL_CFLAGS += -DIGNORE_MISC_WIPE_DATA endif +ifeq ($(BOOTLOADER_MESSAGE_OFFSET),) + LOCAL_CFLAGS += -DBOARD_RECOVERY_BLDRMSG_OFFSET=0 +else + LOCAL_CFLAGS += -DBOARD_RECOVERY_BLDRMSG_OFFSET=$(BOOTLOADER_MESSAGE_OFFSET) +endif LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include include $(BUILD_SHARED_LIBRARY) diff --git a/bootloader_message_twrp/bootloader_message.cpp b/bootloader_message_twrp/bootloader_message.cpp index a06ad9a89f..53dffdcb68 100644 --- a/bootloader_message_twrp/bootloader_message.cpp +++ b/bootloader_message_twrp/bootloader_message.cpp @@ -28,6 +28,16 @@ #include #include +// Spaces used by misc partition are as below: +// 0 - 2K For bootloader_message +// 2K - 16K Used by Vendor's bootloader (the 2K - 4K range may be optionally used +// as bootloader_message_ab struct) +// 16K - 64K Used by uncrypt and recovery to store wipe_package for A/B devices +// Note that these offsets are admitted by bootloader,recovery and uncrypt, so they +// are not configurable without changing all of them. +static const size_t BOOTLOADER_MESSAGE_OFFSET_IN_MISC = BOARD_RECOVERY_BLDRMSG_OFFSET; +static const size_t WIPE_PACKAGE_OFFSET_IN_MISC = 16 * 1024 + BOOTLOADER_MESSAGE_OFFSET_IN_MISC; + static std::string misc_blkdev; void set_misc_device(const char* name) { @@ -210,6 +220,21 @@ bool clear_bootloader_message(void* err) { bool clear_bootloader_message(std::string* err) { bootloader_message boot = {}; + if (BOOTLOADER_MESSAGE_OFFSET_IN_MISC < sizeof(bootloader_message)) { + return write_misc_partition(&boot, sizeof(boot), 0 /* offset */, err); + } + return write_bootloader_message(boot, err); +} + +// libc++ in 5.1 does not know how to handle a std::string* so this craziness is needed +bool amonet_bootloader_message(void* err) { + std::string &s = *(static_cast(err)); + return amonet_bootloader_message(&s); +} + +bool amonet_bootloader_message(std::string* err) { + bootloader_message boot = {}; + strlcpy(boot.command, "boot-amonet", sizeof(boot.command)); return write_bootloader_message(boot, err); } diff --git a/bootloader_message_twrp/include/bootloader_message_twrp/bootloader_message.h b/bootloader_message_twrp/include/bootloader_message_twrp/bootloader_message.h index 52c1b86f0e..e10e2e827c 100644 --- a/bootloader_message_twrp/include/bootloader_message_twrp/bootloader_message.h +++ b/bootloader_message_twrp/include/bootloader_message_twrp/bootloader_message.h @@ -21,21 +21,6 @@ #include #include -// Spaces used by misc partition are as below: -// 0 - 2K For bootloader_message -// 2K - 16K Used by Vendor's bootloader (the 2K - 4K range may be optionally used -// as bootloader_message_ab struct) -// 16K - 64K Used by uncrypt and recovery to store wipe_package for A/B devices -// Note that these offsets are admitted by bootloader,recovery and uncrypt, so they -// are not configurable without changing all of them. -#ifdef BOARD_RECOVERY_BLDRMSG_OFFSET -static const size_t BOOTLOADER_MESSAGE_OFFSET_IN_MISC = BOARD_RECOVERY_BLDRMSG_OFFSET; -static const size_t WIPE_PACKAGE_OFFSET_IN_MISC = 16 * 1024 + BOOTLOADER_MESSAGE_OFFSET_IN_MISC; -#else -static const size_t BOOTLOADER_MESSAGE_OFFSET_IN_MISC = 0; -static const size_t WIPE_PACKAGE_OFFSET_IN_MISC = 16 * 1024; -#endif - /* Bootloader Message (2-KiB) * * This structure describes the content of a block in flash @@ -211,6 +196,9 @@ bool update_bootloader_message(const std::vector& options, std::str bool clear_bootloader_message(void* err); bool clear_bootloader_message(std::string* err); +bool amonet_bootloader_message(void* err); +bool amonet_bootloader_message(std::string* err); + // Writes the reboot-bootloader reboot reason to the bootloader_message. bool write_reboot_bootloader(std::string* err); diff --git a/crypto/ext4crypt/Decrypt.cpp b/crypto/ext4crypt/Decrypt.cpp index d8542dca72..fb162404d0 100644 --- a/crypto/ext4crypt/Decrypt.cpp +++ b/crypto/ext4crypt/Decrypt.cpp @@ -543,13 +543,16 @@ std::string unwrapSyntheticPasswordBlob(const std::string& spblob_path, const st std::string disk_decryption_secret_key = ""; std::string keystore_alias_subid; - if (!Find_Keystore_Alias_SubID_And_Prep_Files(user_id, keystore_alias_subid, handle_str)) { - printf("failed to scan keystore alias subid and prep keystore files\n"); - return disk_decryption_secret_key; - } + // Can be stored in user 0, so check for both. + if (!Find_Keystore_Alias_SubID_And_Prep_Files(user_id, keystore_alias_subid, handle_str) && + !Find_Keystore_Alias_SubID_And_Prep_Files(0, keystore_alias_subid, handle_str)) + { + printf("failed to scan keystore alias subid and prep keystore files\n"); + return disk_decryption_secret_key; + } // First get the keystore service - sp binder = getKeystoreBinderRetry(); + sp binder = getKeystoreBinderRetry(); #ifdef USE_KEYSTORAGE_4 sp service = interface_cast(binder); #else @@ -1159,15 +1162,15 @@ bool Decrypt_User_Synth_Pass(const userid_t user_id, const std::string& Password printf("e4crypt_unlock_user_key returned fail\n"); return Free_Return(retval, weaver_key, &pwd); } -#ifdef USE_KEYSTORAGE_4 +/*#ifdef USE_KEYSTORAGE_4 if (!e4crypt_prepare_user_storage("", user_id, 0, flags)) { #else if (!e4crypt_prepare_user_storage(nullptr, user_id, 0, flags)) { #endif printf("failed to e4crypt_prepare_user_storage\n"); return Free_Return(retval, weaver_key, &pwd); - } - printf("Decrypted Successfully!\n"); + }*/ + printf("User %i Decrypted Successfully!\n", user_id); retval = true; return Free_Return(retval, weaver_key, &pwd); } @@ -1194,7 +1197,9 @@ int Get_Password_Type(const userid_t user_id, std::string& filename) { } if (pwd.password_type == 1) // In Android this means pattern return 2; // In TWRP this means pattern - else if (pwd.password_type == 2) // In Android this means PIN or password + // In Android <11 type 2 is PIN or password + // In Android 11 type 3 is PIN and type 4 is password + else if (pwd.password_type > 1) return 1; // In TWRP this means PIN or password return 0; // We'll try the default password #else @@ -1249,15 +1254,15 @@ bool Decrypt_User(const userid_t user_id, const std::string& Password) { printf("e4crypt_unlock_user_key returned fail\n"); return false; } -#ifdef USE_KEYSTORAGE_4 +/*#ifdef USE_KEYSTORAGE_4 if (!e4crypt_prepare_user_storage("", user_id, 0, flags)) { #else if (!e4crypt_prepare_user_storage(nullptr, user_id, 0, flags)) { #endif printf("failed to e4crypt_prepare_user_storage\n"); return false; - } - printf("Decrypted Successfully!\n"); + }*/ + printf("User %i Decrypted Successfully!\n", user_id); return true; } if (stat("/data/system_de/0/spblob", &st) == 0) { @@ -1337,14 +1342,14 @@ bool Decrypt_User(const userid_t user_id, const std::string& Password) { printf("e4crypt_unlock_user_key returned fail\n"); return false; } -#ifdef USE_KEYSTORAGE_4 +/*#ifdef USE_KEYSTORAGE_4 if (!e4crypt_prepare_user_storage("", user_id, 0, flags)) { #else if (!e4crypt_prepare_user_storage(nullptr, user_id, 0, flags)) { #endif printf("failed to e4crypt_prepare_user_storage\n"); return false; - } - printf("Decrypted Successfully!\n"); + }*/ + printf("User %i Decrypted Successfully!\n", user_id); return true; } diff --git a/crypto/ext4crypt/Ext4Crypt.cpp b/crypto/ext4crypt/Ext4Crypt.cpp index c9e71fd9bb..9360b1a2e1 100644 --- a/crypto/ext4crypt/Ext4Crypt.cpp +++ b/crypto/ext4crypt/Ext4Crypt.cpp @@ -63,6 +63,7 @@ #define MANAGE_MISC_DIRS 0 #include +#include #include //#include @@ -316,16 +317,6 @@ bool lookup_key_ref(const std::map& key_map, userid_t use return true; } -static bool ensure_policy(const std::string& raw_ref __unused, const std::string& path) { - return true; - // 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; - } - return true;*/ -} - static bool is_numeric(const char* name) { for (const char* p = name; *p != '\0'; p++) { if (!isdigit(*p)) return false; @@ -363,6 +354,9 @@ static bool load_all_de_keys() { if (!install_key(key, &raw_ref)) return false; s_de_key_raw_refs[user_id] = raw_ref; LOG(DEBUG) << "Installed de key for user " << user_id; + + std::string user_prop = "twrp.user." + std::to_string(user_id) + ".decrypt"; + property_set(user_prop.c_str(), "0"); } } // ext4enc:TODO: go through all DE directories, ensure that all user dirs have the @@ -411,13 +405,6 @@ bool e4crypt_init_user0() { // explicit calls to install DE keys for secondary users if (!load_all_de_keys()) return false; } - // We can only safely prepare DE storage here, since CE keys are probably - // entangled with user credentials. The framework will always prepare CE - // storage once CE keys are installed. - if (!e4crypt_prepare_user_storage(nullptr, 0, 0, FLAG_STORAGE_DE)) { - LOG(ERROR) << "Failed to prepare user 0 storage"; - return false; - } // If this is a non-FBE device that recently left an emulated mode, // restore user data directories to known-good state. @@ -458,79 +445,6 @@ bool e4crypt_unlock_user_key(userid_t user_id, int serial __unused, const char* } } else { printf("Emulation mode not supported in TWRP\n"); - // When in emulation mode, we just use chmod. However, we also - // unlock directories when not in emulation mode, to bring devices - // back into a known-good state. - /*if (!emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) || - !emulated_unlock(android::vold::BuildDataMiscCePath(user_id), 01771) || - !emulated_unlock(android::vold::BuildDataMediaCePath(nullptr, user_id), 0770) || - !emulated_unlock(android::vold::BuildDataUserCePath(nullptr, user_id), 0771)) { - LOG(ERROR) << "Failed to unlock user " << user_id; - return false; - }*/ } return true; } - -bool e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id, int serial __unused, - int flags) { - - if (flags & FLAG_STORAGE_DE) { - // DE_sys key - auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id); - auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id); - auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id); - auto foreign_de_path = android::vold::BuildDataProfilesForeignDexDePath(user_id); - - // DE_n key - auto system_de_path = android::vold::BuildDataSystemDePath(user_id); - auto misc_de_path = android::vold::BuildDataMiscDePath(user_id); - auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id); - - if (!prepare_dir(system_legacy_path, 0700, AID_SYSTEM, AID_SYSTEM)) return false; -#if MANAGE_MISC_DIRS - if (!prepare_dir(misc_legacy_path, 0750, multiuser_get_uid(user_id, AID_SYSTEM), - multiuser_get_uid(user_id, AID_EVERYBODY))) return false; -#endif - if (!prepare_dir(profiles_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; - if (!prepare_dir(foreign_de_path, 0773, AID_SYSTEM, AID_SYSTEM)) return false; - - if (!prepare_dir(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false; - if (!prepare_dir(misc_de_path, 01771, AID_SYSTEM, AID_MISC)) return false; - if (!prepare_dir(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; - - // For now, FBE is only supported on internal storage - if (e4crypt_is_native() && volume_uuid == nullptr) { - std::string de_raw_ref; - if (!lookup_key_ref(s_de_key_raw_refs, user_id, &de_raw_ref)) return false; - if (!ensure_policy(de_raw_ref, system_de_path)) return false; - if (!ensure_policy(de_raw_ref, misc_de_path)) return false; - if (!ensure_policy(de_raw_ref, user_de_path)) return false; - } - } - - if (flags & FLAG_STORAGE_CE) { - // CE_n key - auto system_ce_path = android::vold::BuildDataSystemCePath(user_id); - auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id); - auto media_ce_path = android::vold::BuildDataMediaCePath(volume_uuid, user_id); - auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id); - - if (!prepare_dir(system_ce_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false; - if (!prepare_dir(misc_ce_path, 01771, AID_SYSTEM, AID_MISC)) return false; - if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false; - if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; - - // For now, FBE is only supported on internal storage - if (e4crypt_is_native() && volume_uuid == nullptr) { - std::string ce_raw_ref; - if (!lookup_key_ref(s_ce_key_raw_refs, user_id, &ce_raw_ref)) return false; - if (!ensure_policy(ce_raw_ref, system_ce_path)) return false; - if (!ensure_policy(ce_raw_ref, misc_ce_path)) return false; - if (!ensure_policy(ce_raw_ref, media_ce_path)) return false; - if (!ensure_policy(ce_raw_ref, user_ce_path)) return false; - } - } - - return true; -} diff --git a/crypto/ext4crypt/Ext4Crypt.h b/crypto/ext4crypt/Ext4Crypt.h index 57623e35c2..beb5d8fe3d 100644 --- a/crypto/ext4crypt/Ext4Crypt.h +++ b/crypto/ext4crypt/Ext4Crypt.h @@ -38,7 +38,7 @@ bool e4crypt_init_user0(); bool e4crypt_unlock_user_key(userid_t user_id, int serial, const char* token, const char* secret); //bool e4crypt_lock_user_key(userid_t user_id); -bool e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id, int serial, int flags); +//bool e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id, int serial, int flags); //bool e4crypt_destroy_user_storage(const char* volume_uuid, userid_t user_id, int flags); bool lookup_key_ref(const std::map& key_map, userid_t user_id, diff --git a/crypto/ext4crypt/Ext4CryptPie.cpp b/crypto/ext4crypt/Ext4CryptPie.cpp index 548e4e445c..48b4ec963e 100644 --- a/crypto/ext4crypt/Ext4CryptPie.cpp +++ b/crypto/ext4crypt/Ext4CryptPie.cpp @@ -110,9 +110,9 @@ static bool e4crypt_is_emulated() { return property_get_bool("persist.sys.emulate_fbe", false); } -static const char* escape_empty(const std::string& value) { +/*static const char* escape_empty(const std::string& value) { return value.empty() ? "null" : value.c_str(); -} +}*/ static std::string get_de_key_path(userid_t user_id) { return StringPrintf("%s/de/%d", user_key_dir.c_str(), user_id); @@ -155,23 +155,6 @@ static std::string get_ce_key_current_path(const std::string& directory_path) { return directory_path + "/current"; } -/*static bool get_ce_key_new_path(const std::string& directory_path, - const std::vector& paths, - std::string *ce_key_path) { - if (paths.empty()) { - *ce_key_path = get_ce_key_current_path(directory_path); - return true; - } - for (unsigned int i = 0; i < UINT_MAX; i++) { - auto const candidate = StringPrintf("%s/cx%010u", directory_path.c_str(), i); - if (paths[0] < candidate) { - *ce_key_path = candidate; - return true; - } - } - return false; -}*/ - // Discard all keys but the named one; rename it to canonical name. // No point in acting on errors in this; ignore them. static void fixate_user_ce_key(const std::string& directory_path, const std::string &to_fix, @@ -259,15 +242,6 @@ static bool prepare_dir(const std::string& dir, mode_t mode, uid_t uid, gid_t gi return true; } -/*static bool destroy_dir(const std::string& dir) { - LOG(DEBUG) << "Destroying: " << dir; - if (rmdir(dir.c_str()) != 0 && errno != ENOENT) { - PLOG(ERROR) << "Failed to destroy " << dir; - return false; - } - return true; -}*/ - // NB this assumes that there is only one thread listening for crypt commands, because // it creates keys in a fixed location. static bool create_and_install_user_keys(userid_t user_id, bool create_ephemeral) { @@ -327,13 +301,6 @@ static void get_data_file_encryption_modes(PolicyKeyRef* key_ref) { android::base::GetProperty("fbe.filenames", "aes-256-heh"); } -static bool ensure_policy(const PolicyKeyRef& key_ref, const std::string& path) { - 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;*/ -} - static bool is_numeric(const char* name) { for (const char* p = name; *p != '\0'; p++) { if (!isdigit(*p)) return false; @@ -379,6 +346,9 @@ static bool load_all_de_keys() { if (!android::vold::installKey(key, &raw_ref)) return false; s_de_key_raw_refs[user_id] = raw_ref; LOG(DEBUG) << "Installed de key for user " << user_id << std::endl; + + std::string user_prop = "twrp.user." + std::to_string(user_id) + ".decrypt"; + property_set(user_prop.c_str(), "0"); } } // ext4enc:TODO: go through all DE directories, ensure that all user dirs have the @@ -435,13 +405,6 @@ bool e4crypt_init_user0() { // explicit calls to install DE keys for secondary users if (!load_all_de_keys()) return false; } - // We can only safely prepare DE storage here, since CE keys are probably - // entangled with user credentials. The framework will always prepare CE - // storage once CE keys are installed. - if (!e4crypt_prepare_user_storage("", 0, 0, /*android::os::IVold::*/STORAGE_FLAG_DE)) { - LOG(ERROR) << "Failed to prepare user 0 storage" << std::endl; - return false; - } // If this is a non-FBE device that recently left an emulated mode, // restore user data directories to known-good state. @@ -452,92 +415,6 @@ bool e4crypt_init_user0() { return true; } -/*bool e4crypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral) { - LOG(DEBUG) << "TWRP NOT e4crypt_vold_create_user_key for " << user_id << " serial " << serial; - return true; - if (!e4crypt_is_native()) { - return true; - } - // FIXME test for existence of key that is not loaded yet - if (s_ce_key_raw_refs.count(user_id) != 0) { - LOG(ERROR) << "Already exists, can't e4crypt_vold_create_user_key for " << user_id - << " serial " << serial; - // FIXME should we fail the command? - return true; - } - if (!create_and_install_user_keys(user_id, ephemeral)) { - return false; - } - return true; -} - -static void drop_caches() { - // Clean any dirty pages (otherwise they won't be dropped). - sync(); - // Drop inode and page caches. - if (!WriteStringToFile("3", "/proc/sys/vm/drop_caches")) { - PLOG(ERROR) << "Failed to drop caches during key eviction"; - } -} - -static bool evict_ce_key(userid_t user_id) { - LOG(ERROR) << "TWRP NOT evict_ce_key\n"; - return true; - s_ce_keys.erase(user_id); - bool success = true; - std::string raw_ref; - // If we haven't loaded the CE key, no need to evict it. - if (lookup_key_ref(s_ce_key_raw_refs, user_id, &raw_ref)) { - success &= android::vold::evictKey(raw_ref); - drop_caches(); - } - s_ce_key_raw_refs.erase(user_id); - return success; -} - -bool e4crypt_destroy_user_key(userid_t user_id) { - LOG(DEBUG) << "NOT e4crypt_destroy_user_key(" << user_id << ")"; - return true; - if (!e4crypt_is_native()) { - return true; - } - bool success = true; - std::string raw_ref; - success &= evict_ce_key(user_id); - success &= lookup_key_ref(s_de_key_raw_refs, user_id, &raw_ref) - && android::vold::evictKey(raw_ref); - s_de_key_raw_refs.erase(user_id); - auto it = s_ephemeral_users.find(user_id); - if (it != s_ephemeral_users.end()) { - s_ephemeral_users.erase(it); - } else { - for (auto const path: get_ce_key_paths(get_ce_key_directory_path(user_id))) { - success &= android::vold::destroyKey(path); - } - auto de_key_path = get_de_key_path(user_id); - if (android::vold::pathExists(de_key_path)) { - success &= android::vold::destroyKey(de_key_path); - } else { - LOG(INFO) << "Not present so not erasing: " << de_key_path; - } - } - return success; -} - -static bool emulated_lock(const std::string& path) { - if (chmod(path.c_str(), 0000) != 0) { - PLOG(ERROR) << "Failed to chmod " << path; - return false; - } -#if EMULATED_USES_SELINUX - if (setfilecon(path.c_str(), "u:object_r:storage_stub_file:s0") != 0) { - PLOG(WARNING) << "Failed to setfilecon " << path; - return false; - } -#endif - return true; -}*/ - static bool emulated_unlock(const std::string& path, mode_t mode) { if (chmod(path.c_str(), mode) != 0) { PLOG(ERROR) << "Failed to chmod " << path << std::endl; @@ -566,92 +443,6 @@ static bool parse_hex(const std::string& hex, std::string* result) { return true; } -static std::string volkey_path(const std::string& misc_path, const std::string& volume_uuid) { - return misc_path + "/vold/volume_keys/" + volume_uuid + "/default"; -} - -static std::string volume_secdiscardable_path(const std::string& volume_uuid) { - return systemwide_volume_key_dir + "/" + volume_uuid + "/secdiscardable"; -} - -static bool read_or_create_volkey(const std::string& misc_path, const std::string& volume_uuid, - PolicyKeyRef* key_ref) { - auto secdiscardable_path = volume_secdiscardable_path(volume_uuid); - std::string secdiscardable_hash; - bool wrapped_key_supported = false; - if (android::vold::pathExists(secdiscardable_path)) { - if (!android::vold::readSecdiscardable(secdiscardable_path, &secdiscardable_hash)) - return false; - } else { - if (fs_mkdirs(secdiscardable_path.c_str(), 0700) != 0) { - PLOG(ERROR) << "Creating directories for: " << secdiscardable_path << std::endl; - return false; - } - if (!android::vold::createSecdiscardable(secdiscardable_path, &secdiscardable_hash)) - return false; - } - auto key_path = volkey_path(misc_path, volume_uuid); - if (fs_mkdirs(key_path.c_str(), 0700) != 0) { - PLOG(ERROR) << "Creating directories for: " << key_path << std::endl; - return false; - } - android::vold::KeyAuthentication auth("", secdiscardable_hash); - wrapped_key_supported = is_wrapped_key_supported_external(); - if (!android::vold::retrieveAndInstallKey(true, auth, key_path, key_path + "_tmp", - &key_ref->key_raw_ref, wrapped_key_supported)) - return false; - key_ref->contents_mode = - android::base::GetProperty("ro.crypto.volume.contents_mode", "aes-256-xts"); - key_ref->filenames_mode = - android::base::GetProperty("ro.crypto.volume.filenames_mode", "aes-256-heh"); - return true; -} - -/*static bool destroy_volkey(const std::string& misc_path, const std::string& volume_uuid) { - auto path = volkey_path(misc_path, volume_uuid); - if (!android::vold::pathExists(path)) return true; - return android::vold::destroyKey(path); -} - -bool e4crypt_add_user_key_auth(userid_t user_id, int serial, const std::string& token_hex, - const std::string& secret_hex) { - LOG(DEBUG) << "e4crypt_add_user_key_auth " << user_id << " serial=" << serial - << " token_present=" << (token_hex != "!"); - if (!e4crypt_is_native()) return true; - if (s_ephemeral_users.count(user_id) != 0) return true; - std::string token, secret; - if (!parse_hex(token_hex, &token)) return false; - if (!parse_hex(secret_hex, &secret)) return false; - auto auth = secret.empty() ? kEmptyAuthentication - : android::vold::KeyAuthentication(token, secret); - auto it = s_ce_keys.find(user_id); - if (it == s_ce_keys.end()) { - LOG(ERROR) << "Key not loaded into memory, can't change for user " << user_id; - return false; - } - const auto &ce_key = it->second; - auto const directory_path = get_ce_key_directory_path(user_id); - auto const paths = get_ce_key_paths(directory_path); - std::string ce_key_path; - if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false; - if (!android::vold::storeKeyAtomically(ce_key_path, user_key_temp, auth, ce_key)) return false; - return true; -} - -bool e4crypt_fixate_newest_user_key_auth(userid_t user_id) { - LOG(DEBUG) << "e4crypt_fixate_newest_user_key_auth " << user_id; - if (!e4crypt_is_native()) return true; - if (s_ephemeral_users.count(user_id) != 0) return true; - auto const directory_path = get_ce_key_directory_path(user_id); - auto const paths = get_ce_key_paths(directory_path); - if (paths.empty()) { - LOG(ERROR) << "No ce keys present, cannot fixate for user " << user_id; - return false; - } - fixate_user_ce_key(directory_path, paths[0], paths); - return true; -}*/ - // TODO: rename to 'install' for consistency, and take flags to know which keys to install bool e4crypt_unlock_user_key(userid_t user_id, int serial, const std::string& token_hex, const std::string& secret_hex) { @@ -684,224 +475,3 @@ bool e4crypt_unlock_user_key(userid_t user_id, int serial, const std::string& to } return true; } - -// TODO: rename to 'evict' for consistency -/*bool e4crypt_lock_user_key(userid_t user_id) { - LOG(DEBUG) << "TWRP NOTe4crypt_lock_user_key " << user_id; - return true; - if (e4crypt_is_native()) { - return evict_ce_key(user_id); - } else if (e4crypt_is_emulated()) { - // When in emulation mode, we just use chmod - if (!emulated_lock(android::vold::BuildDataSystemCePath(user_id)) || - !emulated_lock(android::vold::BuildDataMiscCePath(user_id)) || - !emulated_lock(android::vold::BuildDataMediaCePath("", user_id)) || - !emulated_lock(android::vold::BuildDataUserCePath("", user_id))) { - LOG(ERROR) << "Failed to lock user " << user_id; - return false; - } - } - - return true; -}*/ - -static bool prepare_subdirs(const std::string& action, const std::string& volume_uuid, - userid_t user_id, int flags) { - LOG(ERROR) << "not actually forking for vold_prepare_subdirs\n"; - return true; - /*if (0 != android::vold::ForkExecvp( - std::vector{prepare_subdirs_path, action, volume_uuid, - std::to_string(user_id), std::to_string(flags)})) { - LOG(ERROR) << "vold_prepare_subdirs failed"; - return false; - } - return true;*/ -} - -bool e4crypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int serial, - int flags) { - LOG(DEBUG) << "e4crypt_prepare_user_storage for volume " << escape_empty(volume_uuid) - << ", user " << user_id << ", serial " << serial << ", flags " << flags << std::endl; - - if (flags & /*android::os::IVold::*/STORAGE_FLAG_DE) { - // DE_sys key - auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id); - auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id); - auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id); - - // DE_n key - auto system_de_path = android::vold::BuildDataSystemDePath(user_id); - auto misc_de_path = android::vold::BuildDataMiscDePath(user_id); - auto vendor_de_path = android::vold::BuildDataVendorDePath(user_id); - auto user_de_path = android::vold::BuildDataUserDePath(nullptr, user_id); - - if (volume_uuid.empty()) { - if (!prepare_dir(system_legacy_path, 0700, AID_SYSTEM, AID_SYSTEM)) return false; -#if MANAGE_MISC_DIRS - if (!prepare_dir(misc_legacy_path, 0750, multiuser_get_uid(user_id, AID_SYSTEM), - multiuser_get_uid(user_id, AID_EVERYBODY))) return false; -#endif - if (!prepare_dir(profiles_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; - if (!prepare_dir(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false; - if (!prepare_dir(misc_de_path, 01771, AID_SYSTEM, AID_MISC)) return false; - if (!prepare_dir(vendor_de_path, 0771, AID_ROOT, AID_ROOT)) return false; - } - if (!prepare_dir(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; - - if (e4crypt_is_native()) { - PolicyKeyRef de_ref; - if (volume_uuid.empty()) { - if (!lookup_key_ref(s_de_key_raw_refs, user_id, &de_ref.key_raw_ref)) return false; - get_data_file_encryption_modes(&de_ref); - if (!ensure_policy(de_ref, system_de_path)) return false; - if (!ensure_policy(de_ref, misc_de_path)) return false; - if (!ensure_policy(de_ref, vendor_de_path)) return false; - } else { - if (!read_or_create_volkey(misc_de_path, nullptr, &de_ref)) return false; - } - if (!ensure_policy(de_ref, user_de_path)) return false; - } - } - - if (flags & /*android::os::IVold::*/STORAGE_FLAG_CE) { - // CE_n key - auto system_ce_path = android::vold::BuildDataSystemCePath(user_id); - auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id); - auto vendor_ce_path = android::vold::BuildDataVendorCePath(user_id); - auto media_ce_path = android::vold::BuildDataMediaCePath(nullptr, user_id); - auto user_ce_path = android::vold::BuildDataUserCePath(nullptr, user_id); - - if (volume_uuid.empty()) { - if (!prepare_dir(system_ce_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false; - if (!prepare_dir(misc_ce_path, 01771, AID_SYSTEM, AID_MISC)) return false; - if (!prepare_dir(vendor_ce_path, 0771, AID_ROOT, AID_ROOT)) return false; - } - if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false; - if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; - - if (e4crypt_is_native()) { - PolicyKeyRef ce_ref; - if (volume_uuid.empty()) { - if (!lookup_key_ref(s_ce_key_raw_refs, user_id, &ce_ref.key_raw_ref)) return false; - get_data_file_encryption_modes(&ce_ref); - if (!ensure_policy(ce_ref, system_ce_path)) return false; - if (!ensure_policy(ce_ref, misc_ce_path)) return false; - if (!ensure_policy(ce_ref, vendor_ce_path)) return false; - } else { - if (!read_or_create_volkey(misc_ce_path, nullptr, &ce_ref)) return false; - } - if (!ensure_policy(ce_ref, media_ce_path)) return false; - if (!ensure_policy(ce_ref, user_ce_path)) return false; - } - - if (volume_uuid.empty()) { - // Now that credentials have been installed, we can run restorecon - // over these paths - // NOTE: these paths need to be kept in sync with libselinux - //android::vold::RestoreconRecursive(system_ce_path); - //android::vold::RestoreconRecursive(misc_ce_path); - } - } - if (!prepare_subdirs("prepare", volume_uuid, user_id, flags)) return false; - return true; -} - -/*bool e4crypt_destroy_user_storage(const std::string& volume_uuid, userid_t user_id, int flags) { - LOG(DEBUG) << "TWRP NOT e4crypt_destroy_user_storage for volume " << escape_empty(volume_uuid) - << ", user " << user_id << ", flags " << flags; - bool res = true; - return res; - - res &= prepare_subdirs("destroy", volume_uuid, user_id, flags); - - if (flags & android::os::IVold::STORAGE_FLAG_CE) { - // CE_n key - auto system_ce_path = android::vold::BuildDataSystemCePath(user_id); - auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id); - auto vendor_ce_path = android::vold::BuildDataVendorCePath(user_id); - auto media_ce_path = android::vold::BuildDataMediaCePath(nullptr, user_id); - auto user_ce_path = android::vold::BuildDataUserCePath(nullptr, user_id); - - res &= destroy_dir(media_ce_path); - res &= destroy_dir(user_ce_path); - if (volume_uuid.empty()) { - res &= destroy_dir(system_ce_path); - res &= destroy_dir(misc_ce_path); - res &= destroy_dir(vendor_ce_path); - } else { - if (e4crypt_is_native()) { - res &= destroy_volkey(misc_ce_path, volume_uuid); - } - } - } - - if (flags & android::os::IVold::STORAGE_FLAG_DE) { - // DE_sys key - auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id); - auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id); - auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id); - - // DE_n key - auto system_de_path = android::vold::BuildDataSystemDePath(user_id); - auto misc_de_path = android::vold::BuildDataMiscDePath(user_id); - auto vendor_de_path = android::vold::BuildDataVendorDePath(user_id); - auto user_de_path = android::vold::BuildDataUserDePath(nullptr, user_id); - - res &= destroy_dir(user_de_path); - if (volume_uuid.empty()) { - res &= destroy_dir(system_legacy_path); -#if MANAGE_MISC_DIRS - res &= destroy_dir(misc_legacy_path); -#endif - res &= destroy_dir(profiles_de_path); - res &= destroy_dir(system_de_path); - res &= destroy_dir(misc_de_path); - res &= destroy_dir(vendor_de_path); - } else { - if (e4crypt_is_native()) { - res &= destroy_volkey(misc_de_path, volume_uuid); - } - } - } - - return res; -} - -static bool destroy_volume_keys(const std::string& directory_path, const std::string& volume_uuid) { - LOG(ERROR) << "TWRP NOT destroy_volume_keys\n"; - return true; - auto dirp = std::unique_ptr(opendir(directory_path.c_str()), closedir); - if (!dirp) { - PLOG(ERROR) << "Unable to open directory: " + directory_path; - return false; - } - bool res = true; - for (;;) { - errno = 0; - auto const entry = readdir(dirp.get()); - if (!entry) { - if (errno) { - PLOG(ERROR) << "Unable to read directory: " + directory_path; - return false; - } - break; - } - if (entry->d_type != DT_DIR || entry->d_name[0] == '.') { - LOG(DEBUG) << "Skipping non-user " << entry->d_name; - continue; - } - res &= destroy_volkey(directory_path + "/" + entry->d_name, volume_uuid); - } - return res; -} - -bool e4crypt_destroy_volume_keys(const std::string& volume_uuid) { - bool res = true; - LOG(DEBUG) << "TWRP NOT e4crypt_destroy_volume_keys for volume " << escape_empty(volume_uuid); - /*return res; - auto secdiscardable_path = volume_secdiscardable_path(volume_uuid); - res &= android::vold::runSecdiscardSingle(secdiscardable_path); - res &= destroy_volume_keys("/data/misc_ce", volume_uuid); - res &= destroy_volume_keys("/data/misc_de", volume_uuid); - return res; -}*/ diff --git a/crypto/ext4crypt/Ext4CryptPie.h b/crypto/ext4crypt/Ext4CryptPie.h index d6d6ecf285..7236bc00f0 100644 --- a/crypto/ext4crypt/Ext4CryptPie.h +++ b/crypto/ext4crypt/Ext4CryptPie.h @@ -32,8 +32,8 @@ bool e4crypt_unlock_user_key(userid_t user_id, int serial, const std::string& to const std::string& secret); //bool e4crypt_lock_user_key(userid_t user_id); -bool e4crypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int serial, - int flags); +/*bool e4crypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int serial, + int flags);*/ /*bool e4crypt_destroy_user_storage(const std::string& volume_uuid, userid_t user_id, int flags); bool e4crypt_destroy_volume_keys(const std::string& volume_uuid);*/ diff --git a/crypto/ext4crypt/Keymaster.cpp b/crypto/ext4crypt/Keymaster.cpp index 3c21aa26d6..ec80ab58ce 100644 --- a/crypto/ext4crypt/Keymaster.cpp +++ b/crypto/ext4crypt/Keymaster.cpp @@ -130,14 +130,14 @@ bool KeymasterOperation::updateCompletely(const std::string& input, std::string* auto error = mDevice->update(mOpHandle, nullptr, &inputBlob, &inputConsumed, nullptr, &outputBlob); if (error != KM_ERROR_OK) { - LOG(ERROR) << "update failed, code " << error; + LOG(ERROR) << "update failed, code " << error << "\n"; mDevice = nullptr; return false; } output->append(reinterpret_cast(outputBlob.data), outputBlob.data_length); free(const_cast(outputBlob.data)); if (inputConsumed > toRead) { - LOG(ERROR) << "update reported too much input consumed"; + LOG(ERROR) << "update reported too much input consumed\n"; mDevice = nullptr; return false; } @@ -150,7 +150,7 @@ bool KeymasterOperation::finish() { auto error = mDevice->finish(mOpHandle, nullptr, nullptr, nullptr, nullptr); mDevice = nullptr; if (error != KM_ERROR_OK) { - LOG(ERROR) << "finish failed, code " << error; + LOG(ERROR) << "finish failed, code " << error << "\n"; return false; } return true; @@ -161,7 +161,7 @@ bool KeymasterOperation::finishWithOutput(std::string* output) { auto error = mDevice->finish(mOpHandle, nullptr, nullptr, nullptr, &outputBlob); mDevice = nullptr; if (error != KM_ERROR_OK) { - LOG(ERROR) << "finish failed, code " << error; + LOG(ERROR) << "finish failed, code " << error << "\n"; return false; } output->assign(reinterpret_cast(outputBlob.data), outputBlob.data_length); @@ -174,14 +174,14 @@ Keymaster::Keymaster() { const hw_module_t* module; int ret = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &module); if (ret != 0) { - LOG(ERROR) << "hw_get_module_by_class returned " << ret; + LOG(ERROR) << "hw_get_module_by_class returned " << ret << "\n"; return; } if (module->module_api_version == KEYMASTER_MODULE_API_VERSION_1_0) { keymaster1_device_t* device; ret = keymaster1_open(module, &device); if (ret != 0) { - LOG(ERROR) << "keymaster1_open returned " << ret; + LOG(ERROR) << "keymaster1_open returned " << ret << "\n"; return; } mDevice = std::make_shared(device); @@ -189,12 +189,12 @@ Keymaster::Keymaster() { keymaster2_device_t* device; ret = keymaster2_open(module, &device); if (ret != 0) { - LOG(ERROR) << "keymaster2_open returned " << ret; + LOG(ERROR) << "keymaster2_open returned " << ret << "\n"; return; } mDevice = std::make_shared(device); } else { - LOG(ERROR) << "module_api_version is " << module->module_api_version; + LOG(ERROR) << "module_api_version is " << module->module_api_version << "\n"; return; } } @@ -203,7 +203,7 @@ Keymaster::Keymaster() { keymaster_key_blob_t keyBlob; auto error = mDevice->generate_key(&inParams, &keyBlob); if (error != KM_ERROR_OK) { - LOG(ERROR) << "generate_key failed, code " << error; + LOG(ERROR) << "generate_key failed, code " << error << "\n"; return false; } key->assign(reinterpret_cast(keyBlob.key_material), keyBlob.key_material_size); @@ -215,7 +215,7 @@ bool Keymaster::deleteKey(const std::string& key) { keymaster_key_blob_t keyBlob{reinterpret_cast(key.data()), key.size()}; auto error = mDevice->delete_key(&keyBlob); if (error != KM_ERROR_OK) { - LOG(ERROR) << "delete_key failed, code " << error; + LOG(ERROR) << "delete_key failed, code " << error << "\n"; return false; } return true; @@ -229,7 +229,7 @@ KeymasterOperation Keymaster::begin(keymaster_purpose_t purpose, const std::stri keymaster_key_param_set_t outParams_set; auto error = mDevice->begin(purpose, &keyBlob, &inParams, &outParams_set, &mOpHandle); if (error != KM_ERROR_OK) { - LOG(ERROR) << "begin failed, code " << error; + LOG(ERROR) << "begin failed, code " << error << "\n"; return KeymasterOperation(nullptr, mOpHandle); } outParams->Clear(); @@ -244,7 +244,7 @@ KeymasterOperation Keymaster::begin(keymaster_purpose_t purpose, const std::stri keymaster_operation_handle_t mOpHandle; auto error = mDevice->begin(purpose, &keyBlob, &inParams, nullptr, &mOpHandle); if (error != KM_ERROR_OK) { - LOG(ERROR) << "begin failed, code " << error; + LOG(ERROR) << "begin failed, code " << error << "\n"; return KeymasterOperation(nullptr, mOpHandle); } return KeymasterOperation(mDevice, mOpHandle); diff --git a/crypto/ext4crypt/Keymaster3.cpp b/crypto/ext4crypt/Keymaster3.cpp index 7862044e8a..f8774f24f9 100644 --- a/crypto/ext4crypt/Keymaster3.cpp +++ b/crypto/ext4crypt/Keymaster3.cpp @@ -56,17 +56,17 @@ bool KeymasterOperation::updateCompletely(const std::string& input, std::string* auto inputBlob = blob2hidlVec(reinterpret_cast(&*it), toRead); auto error = mDevice->update(mOpHandle, hidl_vec(), inputBlob, hidlCB); if (!error.isOk()) { - LOG(ERROR) << "update failed: " << error.description(); + LOG(ERROR) << "update failed: " << error.description() << "\n"; mDevice = nullptr; return false; } if (km_error != ErrorCode::OK) { - LOG(ERROR) << "update failed, code " << int32_t(km_error); + LOG(ERROR) << "update failed, code " << int32_t(km_error) << "\n"; mDevice = nullptr; return false; } if (inputConsumed > toRead) { - LOG(ERROR) << "update reported too much input consumed"; + LOG(ERROR) << "update reported too much input consumed\n"; mDevice = nullptr; return false; } @@ -88,11 +88,11 @@ bool KeymasterOperation::finish(std::string* output) { hidl_vec(), hidlCb); mDevice = nullptr; if (!error.isOk()) { - LOG(ERROR) << "finish failed: " << error.description(); + LOG(ERROR) << "finish failed: " << error.description() << "\n"; return false; } if (km_error != ErrorCode::OK) { - LOG(ERROR) << "finish failed, code " << int32_t(km_error); + LOG(ERROR) << "finish failed, code " << int32_t(km_error) << "\n"; return false; } return true; @@ -114,27 +114,27 @@ Keymaster::Keymaster() { auto error = mDevice->generateKey(inParams.hidl_data(), hidlCb); if (!error.isOk()) { - LOG(ERROR) << "generate_key failed: " << error.description(); + LOG(ERROR) << "generate_key failed: " << error.description() << "\n"; return false; } if (km_error != ErrorCode::OK) { - LOG(ERROR) << "generate_key failed, code " << int32_t(km_error); + LOG(ERROR) << "generate_key failed, code " << int32_t(km_error) << "\n"; return false; } return true; }*/ bool Keymaster::deleteKey(const std::string& key) { - LOG(ERROR) << "NOT deleting key in TWRP"; + LOG(ERROR) << "NOT deleting key in TWRP\n"; return false; /*auto keyBlob = blob2hidlVec(key); auto error = mDevice->deleteKey(keyBlob); if (!error.isOk()) { - LOG(ERROR) << "delete_key failed: " << error.description(); + LOG(ERROR) << "delete_key failed: " << error.description() << "\n"; return false; } if (ErrorCode(error) != ErrorCode::OK) { - LOG(ERROR) << "delete_key failed, code " << uint32_t(ErrorCode(error)); + LOG(ERROR) << "delete_key failed, code " << uint32_t(ErrorCode(error)) << "\n"; return false; } return true;*/ @@ -153,11 +153,11 @@ bool Keymaster::upgradeKey(const std::string& oldKey, const AuthorizationSet& in }; auto error = mDevice->upgradeKey(oldKeyBlob, inParams.hidl_data(), hidlCb); if (!error.isOk()) { - LOG(ERROR) << "upgrade_key failed: " << error.description(); + LOG(ERROR) << "upgrade_key failed: " << error.description() << "\n"; return false; } if (km_error != ErrorCode::OK) { - LOG(ERROR) << "upgrade_key failed, code " << int32_t(km_error); + LOG(ERROR) << "upgrade_key failed, code " << int32_t(km_error) << "\n"; return false; } return true; @@ -181,11 +181,11 @@ KeymasterOperation Keymaster::begin(KeyPurpose purpose, const std::string& key, auto error = mDevice->begin(purpose, keyBlob, inParams.hidl_data(), hidlCb); if (!error.isOk()) { - LOG(ERROR) << "begin failed: " << error.description(); + LOG(ERROR) << "begin failed: " << error.description() << "\n"; return KeymasterOperation(ErrorCode::UNKNOWN_ERROR); } if (km_error != ErrorCode::OK) { - LOG(ERROR) << "begin failed, code " << int32_t(km_error); + LOG(ERROR) << "begin failed, code " << int32_t(km_error) << "\n"; return KeymasterOperation(km_error); } return KeymasterOperation(mDevice, mOpHandle); @@ -207,7 +207,7 @@ using namespace ::android::vold; int keymaster_compatibility_cryptfs_scrypt() { Keymaster dev; if (!dev) { - LOG(ERROR) << "Failed to initiate keymaster session"; + LOG(ERROR) << "Failed to initiate keymaster session\n"; return -1; } return dev.isSecure(); @@ -224,11 +224,11 @@ int keymaster_compatibility_cryptfs_scrypt() { Keymaster dev; std::string key; if (!dev) { - LOG(ERROR) << "Failed to initiate keymaster session"; + LOG(ERROR) << "Failed to initiate keymaster session\n"; return -1; } if (!key_buffer || !key_out_size) { - LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":Invalid argument"; + LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":Invalid argument\n"; return -1; } if (key_out_size) { @@ -276,11 +276,11 @@ int keymaster_sign_object_for_cryptfs_scrypt(const uint8_t* key_blob, { Keymaster dev; if (!dev) { - LOG(ERROR) << "Failed to initiate keymaster session"; + LOG(ERROR) << "Failed to initiate keymaster session\n"; return -1; } if (!key_blob || !object || !signature_buffer || !signature_buffer_size) { - LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":Invalid argument"; + LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":Invalid argument\n"; return -1; } @@ -303,7 +303,7 @@ int keymaster_sign_object_for_cryptfs_scrypt(const uint8_t* key_blob, std::string newKey; bool ret = dev.upgradeKey(key, paramBuilder, &newKey); if(ret == false) { - LOG(ERROR) << "Error upgradeKey: "; + LOG(ERROR) << "Error upgradeKey: \n"; return -1; } @@ -312,7 +312,7 @@ int keymaster_sign_object_for_cryptfs_scrypt(const uint8_t* key_blob, } if (key_buffer_size < newKey.size()) { - LOG(ERROR) << "key buffer size is too small"; + LOG(ERROR) << "key buffer size is too small\n"; return -1; } @@ -322,24 +322,24 @@ int keymaster_sign_object_for_cryptfs_scrypt(const uint8_t* key_blob, } if (op.errorCode() != ErrorCode::OK) { - LOG(ERROR) << "Error starting keymaster signature transaction: " << int32_t(op.errorCode()); + LOG(ERROR) << "Error starting keymaster signature transaction: " << int32_t(op.errorCode()) << "\n"; return -1; } if (!op.updateCompletely(input, &output)) { LOG(ERROR) << "Error sending data to keymaster signature transaction: " - << uint32_t(op.errorCode()); + << uint32_t(op.errorCode()) << "\n"; return -1; } if (!op.finish(&output)) { - LOG(ERROR) << "Error finalizing keymaster signature transaction: " << int32_t(op.errorCode()); + LOG(ERROR) << "Error finalizing keymaster signature transaction: " << int32_t(op.errorCode()) << "\n"; return -1; } *signature_buffer = reinterpret_cast(malloc(output.size())); if (*signature_buffer == nullptr) { - LOG(ERROR) << "Error allocation buffer for keymaster signature"; + LOG(ERROR) << "Error allocation buffer for keymaster signature\n"; return -1; } *signature_buffer_size = output.size(); diff --git a/crypto/ext4crypt/Keymaster4.cpp b/crypto/ext4crypt/Keymaster4.cpp index 6507bb1806..3a0ec5984e 100644 --- a/crypto/ext4crypt/Keymaster4.cpp +++ b/crypto/ext4crypt/Keymaster4.cpp @@ -158,11 +158,11 @@ km::ErrorCode Keymaster::exportKey(km::KeyFormat format, KeyBuffer& kmKey, const }; auto error = mDevice->exportKey(format, kmKeyBlob, kmClientId, kmAppData, hidlCb); if (!error.isOk()) { - LOG(ERROR) << "export_key failed: " << error.description(); + LOG(ERROR) << "export_key failed: " << error.description() << std::endl; return km::ErrorCode::UNKNOWN_ERROR; } if (km_error != km::ErrorCode::OK) { - LOG(ERROR) << "export_key failed, code " << int32_t(km_error); + LOG(ERROR) << "export_key failed, code " << int32_t(km_error) << std::endl; return km_error; } return km::ErrorCode::OK; @@ -174,11 +174,11 @@ bool Keymaster::deleteKey(const std::string& key) { auto keyBlob = km::support::blob2hidlVec(key); auto error = mDevice->deleteKey(keyBlob); if (!error.isOk()) { - LOG(ERROR) << "delete_key failed: " << error.description(); + LOG(ERROR) << "delete_key failed: " << error.description() << std::endl; return false; } if (error != km::ErrorCode::OK) { - LOG(ERROR) << "delete_key failed, code " << int32_t(km::ErrorCode(error)); + LOG(ERROR) << "delete_key failed, code " << int32_t(km::ErrorCode(error)) << std::endl; return false; } return true; diff --git a/crypto/ext4crypt/e4policyget.cpp b/crypto/ext4crypt/e4policyget.cpp old mode 100644 new mode 100755 index 05de86fe70..9211347024 --- a/crypto/ext4crypt/e4policyget.cpp +++ b/crypto/ext4crypt/e4policyget.cpp @@ -23,13 +23,12 @@ #define EXT4_KEY_DESCRIPTOR_SIZE_HEX 17 int main(int argc, char *argv[]) { - bool ret = false; if (argc != 2) { printf("Must specify a path\n"); return -1; } else { ext4_encryption_policy eep; - if (e4crypt_policy_get_struct(argv[1], &eep, sizeof(eep))) { + if (e4crypt_policy_get_struct(argv[1], &eep)) { char policy_hex[EXT4_KEY_DESCRIPTOR_SIZE_HEX]; policy_to_hex(eep.master_key_descriptor, policy_hex); printf("%s\n", policy_hex); diff --git a/crypto/fde/cryptfs.cpp b/crypto/fde/cryptfs.cpp index 83522968be..60912fbfaa 100644 --- a/crypto/fde/cryptfs.cpp +++ b/crypto/fde/cryptfs.cpp @@ -60,6 +60,9 @@ //#include "f2fs_sparseblock.h" //#include "EncryptInplace.h" //#include "Process.h" +#if TW_KEYMASTER_MAX_API > 1 +#include +#endif #if TW_KEYMASTER_MAX_API == 3 #include "../ext4crypt/Keymaster3.h" #endif @@ -149,7 +152,7 @@ static void get_blkdev_size(int fd, unsigned long *nr_sec) } } -#if TW_KEYMASTER_MAX_API == 0 +#if TW_KEYMASTER_MAX_API == 0 //TW_KEYMASTER_MAX_API static int keymaster_init(keymaster_device_t **keymaster_dev) { int rc; @@ -174,7 +177,52 @@ static int keymaster_init(keymaster_device_t **keymaster_dev) *keymaster_dev = NULL; return rc; } -#else //TW_KEYMASTER_MAX_API == 0 +#elif TW_KEYMASTER_MAX_API > 1 +static int keymaster_init(keymaster0_device_t **keymaster0_dev, + keymaster1_device_t **keymaster1_dev, + keymaster2_device_t **keymaster2_dev) +{ + int rc; + + const hw_module_t* mod; + rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod); + if (rc) { + printf("could not find any keystore module\n"); + goto err; + } + + printf("keymaster module name is %s\n", mod->name); + printf("keymaster version is %d\n", mod->module_api_version); + + *keymaster0_dev = NULL; + *keymaster1_dev = NULL; + *keymaster2_dev = NULL; + if (mod->module_api_version == KEYMASTER_MODULE_API_VERSION_2_0) { + printf("Found keymaster2 module, using keymaster2 API.\n"); + rc = keymaster2_open(mod, keymaster2_dev); + } else if (mod->module_api_version == KEYMASTER_MODULE_API_VERSION_1_0) { + printf("Found keymaster1 module, using keymaster1 API.\n"); + rc = keymaster1_open(mod, keymaster1_dev); + } else { + printf("Found keymaster0 module, using keymaster0 API.\n"); + rc = keymaster0_open(mod, keymaster0_dev); + } + + if (rc) { + printf("could not open keymaster device in %s (%s)\n", + KEYSTORE_HARDWARE_MODULE_ID, strerror(-rc)); + goto err; + } + + return 0; + +err: + *keymaster0_dev = NULL; + *keymaster1_dev = NULL; + *keymaster2_dev = NULL; + return rc; +} +#else static int keymaster_init(keymaster0_device_t **keymaster0_dev, keymaster1_device_t **keymaster1_dev) { @@ -213,7 +261,7 @@ static int keymaster_init(keymaster0_device_t **keymaster0_dev, *keymaster1_dev = NULL; return rc; } -#endif //TW_KEYMASTER_MAX_API == 0 +#endif //TW_KEYMASTER_MAX_API #ifdef CONFIG_HW_DISK_ENCRYPTION static int scrypt_keymaster(const char *passwd, const unsigned char *salt, @@ -256,7 +304,7 @@ static int get_keymaster_hw_fde_passwd(const char* passwd, unsigned char* newpw, if (should_use_keymaster()) { if (scrypt_keymaster(passwd, salt, newpw, (void*)ftr)) { - SLOGE("scrypt failed"); + SLOGE("scrypt failed\n"); } else { rc = 0; } @@ -293,7 +341,7 @@ static int verify_and_update_hw_fde_passwd(const char *passwd, ++crypt_ftr->failed_decrypt_count; if (ascii_passwd_updated) { - SLOGI("Ascii password was updated"); + SLOGI("Ascii password was updated\n"); } else { /* Code in else part would execute only once: * When device is upgraded from L->M release. @@ -305,14 +353,14 @@ static int verify_and_update_hw_fde_passwd(const char *passwd, if (crypt_ftr->crypt_type == CRYPT_TYPE_DEFAULT) { new_passwd = (char*)malloc(strlen(DEFAULT_HEX_PASSWORD) + 1); if (new_passwd == NULL) { - SLOGE("System out of memory. Password verification incomplete"); + SLOGE("System out of memory. Password verification incomplete\n"); goto out; } strlcpy(new_passwd, DEFAULT_HEX_PASSWORD, strlen(DEFAULT_HEX_PASSWORD) + 1); } else { new_passwd = (char*)malloc(strlen(passwd) * 2 + 1); if (new_passwd == NULL) { - SLOGE("System out of memory. Password verification incomplete"); + SLOGE("System out of memory. Password verification incomplete\n"); goto out; } convert_key_to_hex_ascii_for_upgrade((const unsigned char*)passwd, @@ -322,7 +370,7 @@ static int verify_and_update_hw_fde_passwd(const char *passwd, (char*) crypt_ftr->crypto_type_name); if (key_index >=0) { crypt_ftr->failed_decrypt_count = 0; - SLOGI("Hex password verified...will try to update with Ascii value"); + SLOGI("Hex password verified...will try to update with Ascii value\n"); /* Before updating password, tie that with keymaster to tie with ROT */ if (get_keymaster_hw_fde_passwd(passwd, newpw, @@ -336,9 +384,9 @@ static int verify_and_update_hw_fde_passwd(const char *passwd, if (passwd_updated >= 0) { crypt_ftr->flags |= CRYPT_ASCII_PASSWORD_UPDATED; - SLOGI("Ascii password recorded and updated"); + SLOGI("Ascii password recorded and updated\n"); } else { - SLOGI("Passwd verified, could not update...Will try next time"); + SLOGI("Passwd verified, could not update...Will try next time\n"); } } else { ++crypt_ftr->failed_decrypt_count; @@ -412,10 +460,10 @@ static int keymaster_sign_object(struct crypt_mnt_ftr *ftr, // so) because we really should be using a proper deterministic // RSA padding function, such as PKCS1. memcpy(to_sign + 1, object, min((size_t)RSA_KEY_SIZE_BYTES - 1, object_size)); - SLOGI("Signing safely-padded object"); + SLOGI("Signing safely-padded object\n"); break; default: - SLOGE("Unknown KDF type %d", ftr->kdf_type); + SLOGE("Unknown KDF type %d\n", ftr->kdf_type); return -1; } @@ -424,7 +472,12 @@ static int keymaster_sign_object(struct crypt_mnt_ftr *ftr, #if TW_KEYMASTER_MAX_API >= 1 keymaster0_device_t *keymaster0_dev = 0; keymaster1_device_t *keymaster1_dev = 0; +#if TW_KEYMASTER_MAX_API > 1 + keymaster2_device_t *keymaster2_dev = 0; + if (keymaster_init(&keymaster0_dev, &keymaster1_dev, &keymaster2_dev)) { +#else if (keymaster_init(&keymaster0_dev, &keymaster1_dev)) { +#endif #else keymaster_device_t *keymaster0_dev = 0; if (keymaster_init(&keymaster0_dev)) { @@ -504,6 +557,84 @@ static int keymaster_sign_object(struct crypt_mnt_ftr *ftr, *signature_size = tmp_sig.data_length; rc = 0; } +#if TW_KEYMASTER_MAX_API > 1 + else if (keymaster2_dev) { + keymaster_key_blob_t key = { ftr->keymaster_blob, ftr->keymaster_blob_size }; + keymaster_key_param_t params[] = { + keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE), + keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE), + }; + keymaster_key_param_set_t param_set = { params, sizeof(params)/sizeof(*params) }; + keymaster_operation_handle_t op_handle; + keymaster_key_param_t config_params[] = { + // Set these to crazy values so we don't need to synchronize + // the recovery with system updates. + // key upgrades will be required; it will be upgraded in-memory + keymaster_param_int(KM_TAG_OS_VERSION, 999999), + keymaster_param_int(KM_TAG_OS_PATCHLEVEL, 209912), + }; + keymaster_key_param_set_t config_param_set = { config_params, sizeof(config_params)/sizeof(*config_params) }; + keymaster2_dev->configure(keymaster2_dev, &config_param_set); + keymaster_error_t error = keymaster2_dev->begin(keymaster2_dev, KM_PURPOSE_SIGN, &key, + ¶m_set, NULL /* out_params */, + &op_handle); + if (error == KM_ERROR_KEY_RATE_LIMIT_EXCEEDED) { + // Key usage has been rate-limited. Wait a bit and try again. + sleep(KEYMASTER_CRYPTFS_RATE_LIMIT); + error = keymaster2_dev->begin(keymaster2_dev, KM_PURPOSE_SIGN, &key, + ¶m_set, NULL /* out_params */, + &op_handle); + } + + if (error == KM_ERROR_KEY_REQUIRES_UPGRADE) { + // Upgrade key in-memory if required + // Do not actually write it back; just keep it in memory + const keymaster_key_blob_t key_to_upd = key; + keymaster2_dev->upgrade_key(keymaster2_dev, &key_to_upd, &config_param_set, &key); + error = keymaster2_dev->begin(keymaster2_dev, KM_PURPOSE_SIGN, &key, + ¶m_set, NULL /* out_params */, + &op_handle); + } + + if (error != KM_ERROR_OK) { + printf("Error starting keymaster signature transaction: %d\n", error); + rc = -1; + goto out; + } + + keymaster_blob_t input = { to_sign, to_sign_size }; + size_t input_consumed; + error = keymaster2_dev->update(keymaster2_dev, op_handle, NULL /* in_params */, + &input, &input_consumed, NULL /* out_params */, + NULL /* output */); + if (error != KM_ERROR_OK) { + printf("Error sending data to keymaster signature transaction: %d\n", error); + rc = -1; + goto out; + } + if (input_consumed != to_sign_size) { + // This should never happen. If it does, it's a bug in the keymaster implementation. + printf("Keymaster update() did not consume all data.\n"); + keymaster2_dev->abort(keymaster2_dev, op_handle); + rc = -1; + goto out; + } + + keymaster_blob_t tmp_sig; + error = keymaster2_dev->finish(keymaster2_dev, op_handle, NULL /* in_params */, + NULL, NULL /* verify signature */, NULL /* out_params */, + &tmp_sig); + if (error != KM_ERROR_OK) { + printf("Error finishing keymaster signature transaction: %d\n", error); + rc = -1; + goto out; + } + + *signature = (uint8_t*)tmp_sig.data; + *signature_size = tmp_sig.data_length; + rc = 0; + } +#endif // TW_KEYMASTER_API > 1 #endif // TW_KEYMASTER_API >= 1 out: @@ -528,7 +659,9 @@ static int keymaster_sign_object(struct crypt_mnt_ftr *ftr, ftr->keymaster_blob, KEYMASTER_BLOB_SIZE, &ftr->keymaster_blob_size); #endif //TW_KEYMASTER_MAX_API == 3 #if TW_KEYMASTER_MAX_API >= 4 - //for (;;) { + for (int c = 1;c <= 20;c++) { // 20 tries are enough for signing keymaster + if (c > 2) + usleep(5000); // if failed in two tries lets rest auto result = keymaster_sign_object_for_cryptfs_scrypt( ftr->keymaster_blob, ftr->keymaster_blob_size, KEYMASTER_CRYPTFS_RATE_LIMIT, to_sign, to_sign_size, signature, signature_size); @@ -549,11 +682,10 @@ static int keymaster_sign_object(struct crypt_mnt_ftr *ftr, return -1; } /*if (put_crypt_ftr_and_key(ftr) != 0) { - SLOGE("Failed to write upgraded key to disk"); + SLOGE("Failed to write upgraded key to disk\n"); }*/ SLOGD("Key upgraded successfully\n"); - return 0; - //} + } #endif return -1; } @@ -912,7 +1044,10 @@ static int load_crypto_mapping_table(struct crypt_mnt_ftr *crypt_ftr, tgt->length = crypt_ftr->fs_size; crypt_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); buff_offset = crypt_params - buffer; - SLOGI("Extra parameters for dm_crypt: %s\n", extra_params); + SLOGI( + "Creating crypto dev \"%s\"; cipher=%s, keysize=%u, real_dev=%s, len=%llu, params=\"%s\"\n", + name, crypt_ftr->crypto_type_name, crypt_ftr->keysize, real_blk_name, tgt->length * 512, + extra_params); #ifdef CONFIG_HW_DISK_ENCRYPTION if(is_hw_disk_encryption((char*)crypt_ftr->crypto_type_name)) { @@ -930,8 +1065,8 @@ static int load_crypto_mapping_table(struct crypt_mnt_ftr *crypt_ftr, crypt_ftr->crypto_type_name, master_key_ascii, real_blk_name, extra_params); - SLOGI("target_type = %s", tgt->target_type); - SLOGI("real_blk_name = %s, extra_params = %s", real_blk_name, extra_params); + SLOGI("target_type = %s\n", tgt->target_type); + SLOGI("real_blk_name = %s, extra_params = %s\n", real_blk_name, extra_params); #else convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii); strlcpy(tgt->target_type, "crypt", DM_MAX_TYPE_NAME); @@ -945,7 +1080,9 @@ static int load_crypto_mapping_table(struct crypt_mnt_ftr *crypt_ftr, tgt->next = crypt_params - buffer; for (i = 0; i < TABLE_LOAD_RETRIES; i++) { - if (! ioctl(fd, DM_TABLE_LOAD, io)) { + int ret = ioctl(fd, DM_TABLE_LOAD, io); + if (!ret) { + SLOGI("ioctl err: %d\n", ret); break; } usleep(500000); @@ -1205,13 +1342,13 @@ static int scrypt_keymaster(const char *passwd, const unsigned char *salt, INTERMEDIATE_BUF_SIZE); if (rc) { - SLOGE("scrypt failed"); + SLOGE("scrypt failed\n"); return -1; } if (keymaster_sign_object(ftr, ikey, INTERMEDIATE_BUF_SIZE, &signature, &signature_size)) { - SLOGE("Keymaster signing failed"); + SLOGE("Keymaster signing failed\n"); return -1; } @@ -1220,7 +1357,7 @@ static int scrypt_keymaster(const char *passwd, const unsigned char *salt, free(signature); if (rc) { - SLOGE("scrypt failed"); + SLOGE("scrypt failed\n"); return -1; } @@ -1242,7 +1379,7 @@ static int decrypt_master_key_aux(const char *passwd, unsigned char *salt, /* Turn the password into an intermediate key and IV that can decrypt the master key */ if (kdf(passwd, salt, ikey, kdf_params)) { - SLOGE("kdf failed"); + SLOGE("kdf failed\n"); return -1; } @@ -1308,7 +1445,7 @@ static int decrypt_master_key(const char *passwd, unsigned char *decrypted_maste decrypted_master_key, kdf, kdf_params, intermediate_key, intermediate_key_size); if (ret != 0) { - SLOGW("failure decrypting master key"); + SLOGW("failure decrypting master key\n"); } return ret; @@ -1332,6 +1469,13 @@ static int test_mount_hw_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, int key_index = 0; if(is_hw_disk_encryption((char*)crypt_ftr->crypto_type_name)) { + if (crypt_ftr->flags & CRYPT_FORCE_COMPLETE) { + if (decrypt_master_key(passwd, decrypted_master_key, crypt_ftr, 0, 0)) { + printf("Failed to decrypt master key\n"); + rc = -1; + goto errout; + } + } key_index = verify_and_update_hw_fde_passwd(passwd, crypt_ftr); if (key_index < 0) { rc = -1; @@ -1342,7 +1486,7 @@ static int test_mount_hw_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, #ifndef CONFIG_HW_DISK_ENCRYPT_PERF if (create_crypto_blk_dev(crypt_ftr, (unsigned char*)&key_index, real_blkdev, crypto_blkdev, label, 0)) { - SLOGE("Error creating decrypted block device"); + SLOGE("Error creating decrypted block device\n"); rc = -1; goto errout; } @@ -1350,7 +1494,7 @@ static int test_mount_hw_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, } else { if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key, real_blkdev, crypto_blkdev, label, 0)) { - SLOGE("Error creating decrypted block device"); + SLOGE("Error creating decrypted block device\n"); rc = -1; goto errout; } @@ -1396,7 +1540,7 @@ static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, //char real_blkdev[MAXPATHLEN]; char tmp_mount_point[64]; unsigned int orig_failed_decrypt_count; - int rc; + int rc = 0; int use_keymaster = 0; unsigned char* intermediate_key = 0; size_t intermediate_key_size = 0; @@ -1439,7 +1583,7 @@ static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, if (rc == 0 && memcmp(scrypted_intermediate_key, crypt_ftr->scrypted_intermediate_key, sizeof(scrypted_intermediate_key)) == 0) { - SLOGI("Password matches"); + SLOGI("Password matches\n"); rc = 0; } else { /* Try mounting the file system anyway, just in case the problem's with @@ -1454,7 +1598,7 @@ static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, rc = -1; } else { /* Success! */ - SLOGI("Password did not match but decrypted drive mounted - continue"); + SLOGI("Password did not match but decrypted drive mounted - continue\n"); umount(tmp_mount_point); rc = 0; } @@ -1494,7 +1638,7 @@ int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const unsigned char* key, int keysize, char* out_crypto_blkdev) { int fd = open(real_blkdev, O_RDONLY|O_CLOEXEC); if (fd == -1) { - SLOGE("Failed to open %s: %s", real_blkdev, strerror(errno)); + SLOGE("Failed to open %s: %s\n", real_blkdev, strerror(errno)); return -1; } @@ -1503,7 +1647,7 @@ int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, close(fd); if (nr_sec == 0) { - SLOGE("Failed to get size of %s: %s", real_blkdev, strerror(errno)); + SLOGE("Failed to get size of %s: %s\n", real_blkdev, strerror(errno)); return -1; } @@ -1535,12 +1679,12 @@ int check_unmounted_and_get_ftr(struct crypt_mnt_ftr* crypt_ftr) property_get("ro.crypto.state", encrypted_state, ""); if ( master_key_saved || strcmp(encrypted_state, "encrypted") ) { SLOGE("encrypted fs already validated or not running with encryption," - " aborting"); + " aborting\n"); return -1; } if (get_crypt_ftr_and_key(crypt_ftr)) { - SLOGE("Error getting crypt footer and key"); + SLOGE("Error getting crypt footer and key\n"); return -1; } @@ -1551,11 +1695,11 @@ int check_unmounted_and_get_ftr(struct crypt_mnt_ftr* crypt_ftr) int cryptfs_check_passwd_hw(const char* passwd) { struct crypt_mnt_ftr crypt_ftr; - int rc; + int rc = 0; unsigned char master_key[KEY_LEN_BYTES]; /* get key */ if (get_crypt_ftr_and_key(&crypt_ftr)) { - SLOGE("Error getting crypt footer and key"); + SLOGE("Error getting crypt footer and key\n"); return -1; } @@ -1569,7 +1713,7 @@ int cryptfs_check_passwd_hw(const char* passwd) */ rc = cryptfs_get_master_key(&crypt_ftr, passwd, master_key); if (rc) { - SLOGE("password doesn't match"); + SLOGE("password doesn't match\n"); return rc; } @@ -1577,7 +1721,7 @@ int cryptfs_check_passwd_hw(const char* passwd) DATA_MNT_POINT, CRYPTO_BLOCK_DEVICE); if (rc) { - SLOGE("Default password did not match on reboot encryption"); + SLOGE("Default password did not match on reboot encryption\n"); return rc; } } else { @@ -1593,7 +1737,7 @@ int cryptfs_check_passwd_hw(const char* passwd) int cryptfs_check_passwd(const char *passwd) { /*if (e4crypt_is_native()) { - SLOGE("cryptfs_check_passwd not valid for file encryption"); + SLOGE("cryptfs_check_passwd not valid for file encryption\n"); return -1; }*/ @@ -1602,7 +1746,7 @@ int cryptfs_check_passwd(const char *passwd) rc = check_unmounted_and_get_ftr(&crypt_ftr); if (rc) { - SLOGE("Could not get footer"); + SLOGE("Could not get footer\n"); return rc; } @@ -1615,7 +1759,7 @@ int cryptfs_check_passwd(const char *passwd) DATA_MNT_POINT, CRYPTO_BLOCK_DEVICE); if (rc) { - SLOGE("Password did not match"); + SLOGE("Password did not match\n"); return rc; } @@ -1628,7 +1772,7 @@ int cryptfs_check_passwd(const char *passwd) rc = test_mount_encrypted_fs(&crypt_ftr, DEFAULT_PASSWORD, DATA_MNT_POINT, CRYPTO_BLOCK_DEVICE); if (rc) { - SLOGE("Default password did not match on reboot encryption"); + SLOGE("Default password did not match on reboot encryption\n"); return rc; } } @@ -1645,17 +1789,17 @@ int cryptfs_verify_passwd(const char *passwd) property_get("ro.crypto.state", encrypted_state, ""); if (strcmp(encrypted_state, "encrypted") ) { - SLOGE("device not encrypted, aborting"); + SLOGE("device not encrypted, aborting\n"); return -2; } if (!master_key_saved) { - SLOGE("encrypted fs not yet mounted, aborting"); + SLOGE("encrypted fs not yet mounted, aborting\n"); return -1; } if (!saved_mount_point) { - SLOGE("encrypted fs failed to save mount point, aborting"); + SLOGE("encrypted fs failed to save mount point, aborting\n"); return -1; } @@ -1735,7 +1879,7 @@ int cryptfs_get_master_key(struct crypt_mnt_ftr* ftr, const char* password, &intermediate_key_size); if (rc) { - SLOGE("Can't calculate intermediate key"); + SLOGE("Can't calculate intermediate key\n"); return rc; } @@ -1753,7 +1897,7 @@ int cryptfs_get_master_key(struct crypt_mnt_ftr* ftr, const char* password, free(intermediate_key); if (rc) { - SLOGE("Can't scrypt intermediate key"); + SLOGE("Can't scrypt intermediate key\n"); return rc; } diff --git a/crypto/vold_decrypt/Android.mk b/crypto/vold_decrypt/Android.mk index 860e61f203..c9b99b4b70 100644 --- a/crypto/vold_decrypt/Android.mk +++ b/crypto/vold_decrypt/Android.mk @@ -17,7 +17,6 @@ LOCAL_PATH := $(call my-dir) ifeq ($(TW_INCLUDE_CRYPTO), true) ifneq ($(TW_CRYPTO_USE_SYSTEM_VOLD),) - # Parse TW_CRYPTO_USE_SYSTEM_VOLD ifeq ($(TW_CRYPTO_USE_SYSTEM_VOLD),true) # Just enabled, so only vold + vdc @@ -107,8 +106,20 @@ ifeq ($(TW_INCLUDE_CRYPTO), true) endif endif + ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26; echo $$?),0) + ifeq ($(TW_INCLUDE_LIBRESETPROP), true) + LOCAL_CFLAGS += -DTW_INCLUDE_LIBRESETPROP + endif + endif + LOCAL_SRC_FILES = vold_decrypt.cpp LOCAL_SHARED_LIBRARIES := libcutils + LOCAL_C_INCLUDES += system/extras/ext4_utils/include + ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 29; echo $$?),0) + LOCAL_C_INCLUDES += bootable/recovery/crypto/fscrypt + else + LOCAL_C_INCLUDES += bootable/recovery/crypto/ext4crypt + endif include $(BUILD_STATIC_LIBRARY) ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 28; echo $$?),0) diff --git a/crypto/vold_decrypt/vold_decrypt.cpp b/crypto/vold_decrypt/vold_decrypt.cpp old mode 100644 new mode 100755 index ac872ea280..26801a1fb4 --- a/crypto/vold_decrypt/vold_decrypt.cpp +++ b/crypto/vold_decrypt/vold_decrypt.cpp @@ -243,6 +243,7 @@ bool Service_Exists(const string& initrc_svc) { return (Get_Service_State(initrc_svc) != "error"); } +#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES bool Is_Service_Running(const string& initrc_svc) { return (Get_Service_State(initrc_svc) == "running"); } @@ -250,6 +251,7 @@ bool Is_Service_Running(const string& initrc_svc) { bool Is_Service_Stopped(const string& initrc_svc) { return (Get_Service_State(initrc_svc) == "stopped"); } +#endif bool Start_Service(const string& initrc_svc, int utimeout = SLEEP_MAX_USEC) { string res = "error"; @@ -293,9 +295,11 @@ bool is_Firmware_Mounted(void) { return is_mounted; } +#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES bool will_VendorBin_Be_Symlinked(void) { return (!is_Vendor_Mounted() && TWFunc::Path_Exists("/system/vendor")); } +#endif bool Symlink_Vendor_Folder(void) { bool is_vendor_symlinked = false; @@ -780,6 +784,142 @@ void Set_Needed_Properties(void) { property_set("vendor.sys.listeners.registered", "false"); } +#ifdef TW_INCLUDE_LIBRESETPROP // Patch_Level_Overrides +void Update_Patch_Level(void) { + // On Oreo and above, keymaster requires Android version & patch level to match installed system + // (unless recovery is fastboot booted) + char prop_value[PROPERTY_VALUE_MAX]; + property_get("ro.boot.fastboot", prop_value, "error"); + if (strcmp(prop_value, "error") != 0) { + LOGINFO("Fastboot boot detected. Aborting patch level setting...\n"); + return; + } else { + string sdkverstr = TWFunc::System_Property_Get("ro.build.version.sdk"); + if (!sdkverstr.empty()) { + sdkver = atoi(sdkverstr.c_str()); + } + if (sdkver <= 25) { + property_set("vold_decrypt.legacy_system", "true"); + } else { + LOGINFO("Current system is Oreo or above. Setting OS version and security patch level from installed system...\n"); + property_set("vold_decrypt.legacy_system", "false"); + } + + char legacy_system_value[PROPERTY_VALUE_MAX] = "false"; + property_get("vold_decrypt.legacy_system", prop_value, ""); + + // Only set OS ver and patch level if device uses Oreo+ system + if (strcmp(prop_value, legacy_system_value) == 0) { + property_get("ro.build.version.release", prop_value, ""); + std::string osver_orig = prop_value; + property_set("vold_decrypt.osver_orig", osver_orig.c_str()); + LOGINFO("Current OS version: %s\n", osver_orig.c_str()); + + int error = 0; + std::string osver = TWFunc::System_Property_Get("ro.build.version.release"); + if (!(osver == osver_orig)) { + if (!(error = TWFunc::Property_Override("ro.build.version.release", osver))) { + LOGINFO("Property override successful! New OS version: %s\n", osver.c_str()); + } else { + LOGERROR("Property override failed, code %d\n", error); + return; + } + // TODO: Confirm whether we actually need to update the props in prop.default + std::string sed_osver = "sed -i 's/ro.build.version.release=.*/ro.build.version.release=" + osver + "/g' /prop.default"; + TWFunc::Exec_Cmd(sed_osver); + property_set("vold_decrypt.osver_set", "true"); + } else { + LOGINFO("Current OS version & System OS version already match. Proceeding to next step.\n"); + property_set("vold_decrypt.osver_set", "false"); + } + + property_get("ro.build.version.security_patch", prop_value, ""); + std::string patchlevel_orig = prop_value; + property_set("vold_decrypt.patchlevel_orig", patchlevel_orig.c_str()); + LOGINFO("Current security patch level: %s\n", patchlevel_orig.c_str()); + + std::string patchlevel = TWFunc::System_Property_Get("ro.build.version.security_patch"); + if (!(patchlevel == patchlevel_orig)) { + if (!(error = TWFunc::Property_Override("ro.build.version.security_patch", patchlevel))) { + LOGINFO("Property override successful! New security patch level: %s\n", patchlevel.c_str()); + } else { + LOGERROR("Property override failed, code %d\n", error); + return; + } + // TODO: Confirm whether we actually need to update the props in prop.default + std::string sed_patchlevel = "sed -i 's/ro.build.version.security_patch=.*/ro.build.version.security_patch=" + patchlevel + "/g' /prop.default"; + TWFunc::Exec_Cmd(sed_patchlevel); + property_set("vold_decrypt.patchlevel_set", "true"); + } else { + LOGINFO("Current security patch level & System security patch level already match. Proceeding to next step.\n"); + property_set("vold_decrypt.patchlevel_set", "false"); + } + return; + } else { + LOGINFO("Current system is Nougat or older. Skipping OS version and security patch level setting...\n"); + return; + } + } +} + +void Revert_Patch_Level(void) { + char prop_value[PROPERTY_VALUE_MAX]; + property_get("ro.boot.fastboot", prop_value, "error"); + if (strcmp(prop_value, "error") != 0) { + return; + } else { + char osver_set[PROPERTY_VALUE_MAX]; + char patchlevel_set[PROPERTY_VALUE_MAX]; + char osver_patchlevel_set[PROPERTY_VALUE_MAX] = "false"; + + property_get("vold_decrypt.osver_set", osver_set, ""); + property_get("vold_decrypt.patchlevel_set", patchlevel_set, ""); + + int osver_result = strcmp(osver_set, osver_patchlevel_set); + int patchlevel_result = strcmp(patchlevel_set, osver_patchlevel_set); + if (!(osver_result == 0 && patchlevel_result == 0)) { + LOGINFO("Reverting OS version and security patch level to original TWRP values...\n"); + property_get("vold_decrypt.osver_orig", prop_value, ""); + std::string osver_orig = prop_value; + property_get("ro.build.version.release", prop_value, ""); + std::string osver = prop_value; + + int error = 0; + if (!(osver == osver_orig)) { + if (!(error = TWFunc::Property_Override("ro.build.version.release", osver_orig))) { + LOGINFO("Property override successful! Original OS version: %s\n", osver_orig.c_str()); + } else { + LOGERROR("Property override failed, code %d\n", error); + return; + } + // TODO: Confirm whether we actually need to update the props in prop.default + std::string sed_osver_orig = "sed -i 's/ro.build.version.release=.*/ro.build.version.release=" + osver_orig + "/g' /prop.default"; + TWFunc::Exec_Cmd(sed_osver_orig); + } + + property_get("vold_decrypt.patchlevel_orig", prop_value, ""); + std::string patchlevel_orig = prop_value; + property_get("ro.build.version.security_patch", prop_value, ""); + std::string patchlevel = prop_value; + + if (!(patchlevel == patchlevel_orig)) { + if (!(error = TWFunc::Property_Override("ro.build.version.security_patch", patchlevel_orig))) { + LOGINFO("Property override successful! Original security patch level: %s\n", patchlevel_orig.c_str()); + } else { + LOGERROR("Property override failed, code %d\n", error); + return; + } + // TODO: Confirm whether we actually need to update the props in prop.default + std::string sed_patchlevel_orig = "sed -i 's/ro.build.version.security_patch=.*/ro.build.version.security_patch=" + patchlevel_orig + "/g' /prop.default"; + TWFunc::Exec_Cmd(sed_patchlevel_orig); + } + } else { + return; + } + } +} +#endif // Patch_Level_Overrides + static unsigned int get_blkdev_size(int fd) { unsigned long nr_sec; @@ -1161,6 +1301,9 @@ int Vold_Decrypt_Core(const string& Password) { Symlink_Firmware_Files(is_vendor_symlinked, is_firmware_symlinked); Set_Needed_Properties(); +#ifdef TW_INCLUDE_LIBRESETPROP + Update_Patch_Level(); +#endif // Start services needed for vold decrypt LOGINFO("Starting services...\n"); @@ -1225,7 +1368,9 @@ int Vold_Decrypt_Core(const string& Password) { LOGINFO("Failed to start vold\n"); res = VD_ERR_VOLD_FAILED_TO_START; } - +#ifdef TW_INCLUDE_LIBRESETPROP + Revert_Patch_Level(); +#endif // Stop services needed for vold decrypt so /system can be unmounted LOGINFO("Stopping services...\n"); Stop_Service("sys_vold"); @@ -1245,7 +1390,7 @@ int Vold_Decrypt_Core(const string& Password) { if (is_fstab_symlinked) Restore_Recovery_Fstab(); - if (!PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) { + if (!PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), false)) { // PartitionManager failed to unmount ANDROID_ROOT, this should not happen, // but in case it does, do a lazy unmount LOGINFO("WARNING: '%s' could not be unmounted normally!\n", PartitionManager.Get_Android_Root_Path().c_str()); @@ -1256,7 +1401,7 @@ int Vold_Decrypt_Core(const string& Password) { 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)) { + if (!PartitionManager.UnMount_By_Path(mnt_point, false)) { LOGINFO("WARNING: %s partition could not be unmounted normally!\n", partitions[i].c_str()); umount2(mnt_point.c_str(), MNT_DETACH); } diff --git a/data.cpp b/data.cpp index 088dbda68a..9b2ba49be4 100755 --- a/data.cpp +++ b/data.cpp @@ -25,6 +25,11 @@ #include #include +#ifdef TW_IP_ADDRESS +#include +#include +#endif + #include "variables.h" #include "data.hpp" #include "partitions.hpp" @@ -273,44 +278,6 @@ int DataManager::LoadValues(const string& filename) return 0; } -int DataManager::LoadPersistValues(void) -{ - static bool loaded = false; - string dev_id; - - // Only run this function once, and make sure normal settings file has not yet been read - if (loaded || !mBackingFile.empty() || !TWFunc::Path_Exists(PERSIST_SETTINGS_FILE)) - return -1; - - LOGINFO("Attempt to load settings from /persist settings file...\n"); - - if (!mInitialized) - SetDefaultValues(); - - GetValue("device_id", dev_id); - mPersist.SetFile(PERSIST_SETTINGS_FILE); - mPersist.SetFileVersion(FILE_VERSION); - - // Read in the file, if possible - pthread_mutex_lock(&m_valuesLock); - mPersist.LoadValues(); - -#ifndef TW_NO_SCREEN_TIMEOUT - blankTimer.setTime(mPersist.GetIntValue("tw_screen_timeout_secs")); -#endif - - update_tz_environment_variables(); - TWFunc::Set_Brightness(GetStrValue("tw_brightness")); - - pthread_mutex_unlock(&m_valuesLock); - - /* Don't set storage nor backup paths this early */ - - loaded = true; - - return 0; -} - int DataManager::Flush() { return SaveValues(); @@ -319,15 +286,6 @@ int DataManager::Flush() int DataManager::SaveValues() { #ifndef TW_OEM_BUILD - if (PartitionManager.Mount_By_Path("/persist", false)) { - mPersist.SetFile(PERSIST_SETTINGS_FILE); - mPersist.SetFileVersion(FILE_VERSION); - pthread_mutex_lock(&m_valuesLock); - mPersist.SaveValues(); - pthread_mutex_unlock(&m_valuesLock); - LOGINFO("Saved settings file values to %s\n", PERSIST_SETTINGS_FILE); - } - if (mBackingFile.empty()) return -1; @@ -510,18 +468,56 @@ int DataManager::SetValue(const string& varName, const unsigned long long& value return SetValue(varName, valStr.str(), persist); } +// For legacy code that doesn't set a scope int DataManager::SetProgress(const float Fraction) { - return SetValue("ui_progress", (float) (Fraction * 100.0)); + if (SetValue("ui_portion_size", 0) != 0) + return -1; + if (SetValue("ui_portion_start", 0) != 0) + return -1; + ShowProgress(1, 0); + int res = _SetProgress(Fraction); + if (SetValue("ui_portion_size", 0) != 0) + return -1; + if (SetValue("ui_portion_start", 0) != 0) + return -1; + return res; } -int DataManager::ShowProgress(const float Portion, const float Seconds) +int DataManager::_SetProgress(float Fraction) { + float Portion_Start, Portion_Size; + GetValue("ui_portion_size", Portion_Size); + GetValue("ui_portion_start", Portion_Start); + //LOGINFO("SetProgress(%.2lf): Portion_Size: %.2lf Portion_Start: %.2lf\n", Fraction, Portion_Size, Portion_Start); + if (Fraction < 0.0) + Fraction = 0; + if (Fraction > 1.0) + Fraction = 1; + if (SetValue("ui_progress", (float) ((Portion_Start + (Portion_Size * Fraction)) * 100.0)) != 0) + return -1; + return (SetValue("ui_progress_portion", 0) != 0); +} + +int DataManager::ShowProgress(float Portion, const float Seconds) { - float Starting_Portion; - GetValue("ui_progress_portion", Starting_Portion); - if (SetValue("ui_progress_portion", (float)(Portion * 100.0) + Starting_Portion) != 0) + float Portion_Start, Portion_Size; + GetValue("ui_portion_size", Portion_Size); + GetValue("ui_portion_start", Portion_Start); + Portion_Start += Portion_Size; + if(Portion + Portion_Start > 1.0) + Portion = 1.0 - Portion_Start; + //LOGINFO("ShowProgress(%.2lf, %.2lf): Portion_Start: %.2lf\n", Portion, Seconds, Portion_Start); + if (SetValue("ui_portion_start", Portion_Start) != 0) + return -1; + if (SetValue("ui_portion_size", Portion) != 0) return -1; - if (SetValue("ui_progress_frames", Seconds * 30) != 0) + if (SetValue("ui_progress", (float)(Portion_Start * 100.0)) != 0) return -1; + if(Seconds) { + if (SetValue("ui_progress_portion", (float)((Portion * 100.0) + Portion_Start)) != 0) + return -1; + if (SetValue("ui_progress_frames", Seconds * 48) != 0) + return -1; + } return 0; } @@ -535,7 +531,7 @@ void DataManager::SetBackupFolder() { string str = GetCurrentStoragePath(); TWPartition* partition = PartitionManager.Find_Partition_By_Path(str); - str += "/TWRP/BACKUPS/"; + str += TWFunc::Check_For_TwrpFolder() + "/BACKUPS/"; string dev_id; GetValue("device_id", dev_id); @@ -622,9 +618,11 @@ void DataManager::SetDefaultValues() mConst.SetValue(TW_SHOW_DUMLOCK, "0"); #endif + mData.SetValue(TW_RECOVERY_FOLDER_VAR, TW_DEFAULT_RECOVERY_FOLDER); + str = GetCurrentStoragePath(); mPersist.SetValue(TW_ZIP_LOCATION_VAR, str); - str += "/TWRP/BACKUPS/"; + str += DataManager::GetStrValue(TW_RECOVERY_FOLDER_VAR) + "/BACKUPS/"; string dev_id; mConst.GetValue("device_id", dev_id); @@ -646,6 +644,15 @@ void DataManager::SetDefaultValues() #else mConst.SetValue(TW_REBOOT_BOOTLOADER, "1"); #endif +//#ifdef TW_AMONET +// #define TW_HACKED_BL_BUTTON +//#endif +#ifdef TW_HACKED_BL_BUTTON + printf("TW_HACKED_BL_BUTTON := true\n"); + mConst.SetValue(TW_REBOOT_HACKED_BL, "1"); +#else + mConst.SetValue(TW_REBOOT_HACKED_BL, "0"); +#endif #ifdef RECOVERY_SDCARD_ON_DATA printf("RECOVERY_SDCARD_ON_DATA := true\n"); mConst.SetValue(TW_HAS_DATA_MEDIA, "1"); @@ -736,11 +743,14 @@ void DataManager::SetDefaultValues() #else mConst.SetValue(TW_SDEXT_DISABLE_EXT4, "0"); #endif - -#ifdef TW_HAS_NO_BOOT_PARTITION - mPersist.SetValue("tw_backup_list", "/system;/data;"); +#ifdef TW_DEFAULT_BACKUP_LIST + mPersist.SetValue("tw_backup_list", EXPAND(TW_DEFAULT_BACKUP_LIST)); #else + #ifdef TW_HAS_NO_BOOT_PARTITION + mPersist.SetValue("tw_backup_list", "/system;/data;"); + #else mPersist.SetValue("tw_backup_list", "/system;/data;/boot;"); + #endif #endif mConst.SetValue(TW_MIN_SYSTEM_VAR, TW_MIN_SYSTEM_SIZE); mData.SetValue(TW_BACKUP_NAME, "(Auto Generate)"); @@ -754,6 +764,7 @@ void DataManager::SetDefaultValues() mPersist.SetValue(TW_GUI_SORT_ORDER, "1"); mPersist.SetValue(TW_RM_RF_VAR, "0"); mPersist.SetValue(TW_SKIP_DIGEST_CHECK_VAR, "0"); + mPersist.SetValue(TW_SKIP_DIGEST_CHECK_ZIP_VAR, "1"); mPersist.SetValue(TW_SKIP_DIGEST_GENERATE_VAR, "0"); mPersist.SetValue(TW_SDEXT_SIZE, "0"); mPersist.SetValue(TW_SWAP_SIZE, "0"); @@ -761,6 +772,8 @@ void DataManager::SetDefaultValues() mPersist.SetValue(TW_TIME_ZONE_GUISEL, "CST6;CDT,M3.2.0,M11.1.0"); mPersist.SetValue(TW_TIME_ZONE_GUIOFFSET, "0"); mPersist.SetValue(TW_TIME_ZONE_GUIDST, "1"); + mPersist.SetValue(TW_AUTO_REFLASHTWRP_VAR, "0"); + mData.SetValue(TW_ACTION_BUSY, "0"); mData.SetValue("tw_wipe_cache", "0"); mData.SetValue("tw_wipe_dalvik", "0"); @@ -783,6 +796,13 @@ void DataManager::SetDefaultValues() #else mPersist.SetValue(TW_NO_SHA2, "1"); #endif + mPersist.SetValue(TW_UNMOUNT_SYSTEM, "1"); + +#if defined BOARD_USES_RECOVERY_AS_BOOT && defined BOARD_BUILD_SYSTEM_ROOT_IMAGE + mConst.SetValue("tw_uses_initramfs", "1"); +#else + mConst.SetValue("tw_uses_initramfs", "0"); +#endif #ifdef TW_NO_SCREEN_TIMEOUT mConst.SetValue("tw_screen_timeout_secs", "0"); @@ -912,14 +932,28 @@ void DataManager::SetDefaultValues() mConst.SetValue("tw_app_installed_in_system", "0"); #else mConst.SetValue("tw_oem_build", "0"); - mPersist.SetValue("tw_app_prompt", "1"); - mPersist.SetValue("tw_app_install_system", "1"); - mData.SetValue("tw_app_install_status", "0"); // 0 = no status, 1 = not installed, 2 = already installed + mPersist.SetValue("tw_app_prompt", "0"); + mPersist.SetValue("tw_app_install_system", "0"); + mData.SetValue("tw_app_install_status", "2"); // 0 = no status, 1 = not installed, 2 = already installed mData.SetValue("tw_app_installed_in_system", "0"); #endif +#ifndef TW_EXCLUDE_NANO + mConst.SetValue("tw_include_nano", "1"); +#else + LOGINFO("TW_EXCLUDE_NANO := true\n"); + mConst.SetValue("tw_include_nano", "0"); +#endif + + mData.SetValue("tw_flash_both_slots", "0"); + mData.SetValue("tw_is_slot_part", "0"); mData.SetValue("tw_enable_adb_backup", "0"); + if (TWFunc::Path_Exists("/sbin/logcat")) + mConst.SetValue("tw_logcat_exists", "1"); + else + mConst.SetValue("tw_logcat_exists", "0"); + if (TWFunc::Path_Exists("/sbin/magiskboot")) mConst.SetValue("tw_has_repack_tools", "1"); else @@ -1040,6 +1074,30 @@ int DataManager::GetMagicValue(const string& varName, string& value) value = tmp; return 0; } +#ifdef TW_IP_ADDRESS + else if (varName == "tw_ip_address") + { + char tmp[16]; + static char lastIp[16] = {0}; + static time_t nextIpCheck = 0; + struct timeval curTime; + gettimeofday(&curTime, NULL); + if (curTime.tv_sec > nextIpCheck) + { + struct ifreq ifr = { 0 }; + strcpy(ifr.ifr_name, "eth0"); + int fd = socket(AF_INET, SOCK_DGRAM, 0); + ioctl(fd, SIOCGIFADDR, &ifr); + snprintf(lastIp, 15, "%s", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr)); + close(fd); + nextIpCheck = curTime.tv_sec + 60; + } + + sprintf(tmp, "%s", lastIp); + value = tmp; + return 0; + } +#endif return -1; } @@ -1049,28 +1107,30 @@ void DataManager::Output_Version(void) string Path; char version[255]; - std::string cacheDir = TWFunc::get_cache_dir(); - if (cacheDir.empty()) { + std::string logDir = TWFunc::get_log_dir(); + if (logDir.empty()) { LOGINFO("Unable to find cache directory\n"); return; } - std::string recoveryCacheDir = cacheDir + "recovery/"; + std::string recoveryLogDir = logDir + "recovery/"; - if (cacheDir == NON_AB_CACHE_DIR) { - if (!PartitionManager.Mount_By_Path(NON_AB_CACHE_DIR, false)) { + if (logDir == CACHE_LOGS_DIR) { + if (!PartitionManager.Mount_By_Path(CACHE_LOGS_DIR, false)) { LOGINFO("Unable to mount '%s' to write version number.\n", Path.c_str()); return; } - } - if (!TWFunc::Path_Exists(recoveryCacheDir)) { - LOGINFO("Recreating %s folder.\n", recoveryCacheDir.c_str()); - if (!TWFunc::Create_Dir_Recursive(recoveryCacheDir.c_str(), S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP, 0, 0)) { - LOGERR("DataManager::Output_Version -- Unable to make %s: %s\n", recoveryCacheDir.c_str(), strerror(errno)); - return; + + if (!TWFunc::Path_Exists(recoveryLogDir)) { + LOGINFO("Recreating %s folder.\n", recoveryLogDir.c_str()); + if (!TWFunc::Create_Dir_Recursive(recoveryLogDir.c_str(), S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP, 0, 0)) { + LOGERR("DataManager::Output_Version -- Unable to make %s: %s\n", recoveryLogDir.c_str(), strerror(errno)); + return; + } } } - std::string verPath = recoveryCacheDir + ".version"; + + std::string verPath = recoveryLogDir + ".version"; if (TWFunc::Path_Exists(verPath)) { unlink(verPath.c_str()); } @@ -1082,7 +1142,7 @@ void DataManager::Output_Version(void) strcpy(version, TW_VERSION_STR); fwrite(version, sizeof(version[0]), strlen(version) / sizeof(version[0]), fp); fclose(fp); - TWFunc::copy_file("/etc/recovery.fstab", recoveryCacheDir + "recovery.fstab", 0644); + TWFunc::copy_file("/etc/recovery.fstab", recoveryLogDir + "recovery.fstab", 0644); PartitionManager.Output_Storage_Fstab(); sync(); LOGINFO("Version number saved to '%s'\n", verPath.c_str()); @@ -1101,8 +1161,8 @@ void DataManager::ReadSettingsFile(void) memset(mkdir_path, 0, sizeof(mkdir_path)); memset(settings_file, 0, sizeof(settings_file)); - sprintf(mkdir_path, "%s/TWRP", GetSettingsStoragePath().c_str()); - sprintf(settings_file, "%s/.twrps", mkdir_path); + sprintf(mkdir_path, "%s%s", GetSettingsStoragePath().c_str(), GetStrValue(TW_RECOVERY_FOLDER_VAR).c_str()); + sprintf(settings_file, "%s/%s", mkdir_path, TW_SETTINGS_FILE); if (!PartitionManager.Mount_Settings_Storage(false)) { @@ -1142,3 +1202,11 @@ void DataManager::Vibrate(const string& varName) } #endif } + + +void DataManager::LoadTWRPFolderInfo(void) +{ + string mainPath = GetCurrentStoragePath(); + SetValue(TW_RECOVERY_FOLDER_VAR, TWFunc::Check_For_TwrpFolder()); + mBackingFile = mainPath + GetStrValue(TW_RECOVERY_FOLDER_VAR) + '/' + TW_SETTINGS_FILE; +} diff --git a/data.hpp b/data.hpp index d61fe8e7c0..843bef2076 100755 --- a/data.hpp +++ b/data.hpp @@ -23,8 +23,6 @@ #include #include "infomanager.hpp" -#define PERSIST_SETTINGS_FILE "/persist/.twrps" - using namespace std; class DataManager @@ -34,6 +32,7 @@ class DataManager static int LoadValues(const string& filename); static int LoadPersistValues(void); static int Flush(); + static void LoadTWRPFolderInfo(void); // Core get routines static int GetValue(const string& varName, string& value); @@ -51,7 +50,8 @@ class DataManager static int SetValue(const string& varName, const float value, const int persist = 0); static int SetValue(const string& varName, const unsigned long long& value, const int persist = 0); static int SetProgress(const float Fraction); - static int ShowProgress(const float Portion, const float Seconds); + static int _SetProgress(float Fraction); + static int ShowProgress(float Portion, const float Seconds); static void DumpValues(); static void update_tz_environment_variables(); @@ -64,8 +64,10 @@ class DataManager static string GetCurrentStoragePath(void); static string GetSettingsStoragePath(void); -protected: +public: static string mBackingFile; + +protected: static int mInitialized; static InfoManager mPersist; static InfoManager mData; diff --git a/etc/Android.mk b/etc/Android.mk index ca549ea296..ff9d8b181f 100644 --- a/etc/Android.mk +++ b/etc/Android.mk @@ -14,6 +14,15 @@ LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE := init.recovery.nano.rc +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) + +LOCAL_SRC_FILES := $(LOCAL_MODULE) +include $(BUILD_PREBUILT) + ifneq ($(TW_EXCLUDE_DEFAULT_USB_INIT), true) include $(CLEAR_VARS) @@ -82,7 +91,6 @@ endif ifeq ($(TWRP_INCLUDE_LOGCAT), true) ifeq ($(TARGET_USES_LOGD), true) - include $(CLEAR_VARS) LOCAL_MODULE := init.recovery.logd.rc LOCAL_MODULE_TAGS := eng diff --git a/etc/init.rc b/etc/init.rc index e0889c44d5..a2bef2b206 100644 --- a/etc/init.rc +++ b/etc/init.rc @@ -1,6 +1,7 @@ import /init.recovery.logd.rc import /init.recovery.ldconfig.rc import /init.recovery.mksh.rc +import /init.recovery.nano.rc import /init.recovery.usb.rc import /init.recovery.service.rc import /init.recovery.vold_decrypt.rc @@ -17,6 +18,10 @@ on early-init # Set the security context of /postinstall if present. restorecon /postinstall + # ueventd wants to write to /acct + mount cgroup none /acct cpuacct + mkdir /acct/uid + start ueventd service set_permissive /sbin/permissive.sh @@ -31,9 +36,6 @@ on init export ANDROID_DATA /data export EXTERNAL_STORAGE /sdcard - mount cgroup none /acct cpuacct - mkdir /acct/uid - mkdir /system mkdir /data mkdir /cache diff --git a/etc/init.recovery.nano.rc b/etc/init.recovery.nano.rc new file mode 100644 index 0000000000..8a4e9e172c --- /dev/null +++ b/etc/init.recovery.nano.rc @@ -0,0 +1,3 @@ +on fs + export TERMINFO /sbin/etc/terminfo + export TERM bg1.25 diff --git a/gui/Android.mk b/gui/Android.mk old mode 100644 new mode 100755 index 22b5347702..238bd41374 --- a/gui/Android.mk +++ b/gui/Android.mk @@ -32,6 +32,10 @@ LOCAL_SRC_FILES := \ terminal.cpp \ twmsg.cpp +ifneq ($(TW_DELAY_TOUCH_INIT_MS),) + LOCAL_CFLAGS += -DTW_DELAY_TOUCH_INIT_MS=$(TW_DELAY_TOUCH_INIT_MS) +endif + ifneq ($(TWRP_CUSTOM_KEYBOARD),) LOCAL_SRC_FILES += $(TWRP_CUSTOM_KEYBOARD) else @@ -46,6 +50,15 @@ else LOCAL_SHARED_LIBRARIES += libminzip LOCAL_CFLAGS += -DUSE_MINZIP endif +ifeq ($(TARGET_USERIMAGES_USE_EXT4), true) + ifeq ($(shell test $(PLATFORM_SDK_VERSION) -le 28; echo $$?),0) + LOCAL_C_INCLUDES += system/extras/ext4_utils \ + system/extras/ext4_utils/include \ + $(LOCAL_PATH)/../crypto/ext4crypt + LOCAL_SHARED_LIBRARIES += libext4_utils + endif +endif + LOCAL_MODULE := libguitwrp #TWRP_EVENT_LOGGING := true @@ -55,13 +68,20 @@ endif ifneq ($(TW_USE_KEY_CODE_TOUCH_SYNC),) LOCAL_CFLAGS += -DTW_USE_KEY_CODE_TOUCH_SYNC=$(TW_USE_KEY_CODE_TOUCH_SYNC) endif - +ifneq ($(TW_OZIP_DECRYPT_KEY),) + LOCAL_CFLAGS += -DTW_OZIP_DECRYPT_KEY=\"$(TW_OZIP_DECRYPT_KEY)\" +else + LOCAL_CFLAGS += -DTW_OZIP_DECRYPT_KEY=0 +endif ifneq ($(TW_NO_SCREEN_BLANK),) LOCAL_CFLAGS += -DTW_NO_SCREEN_BLANK endif ifneq ($(TW_NO_SCREEN_TIMEOUT),) LOCAL_CFLAGS += -DTW_NO_SCREEN_TIMEOUT endif +ifneq ($(TW_NO_SCREEN),) + LOCAL_CFLAGS += -DTW_NO_SCREEN +endif ifeq ($(TW_OEM_BUILD), true) LOCAL_CFLAGS += -DTW_OEM_BUILD endif @@ -80,9 +100,22 @@ endif ifeq ($(TW_ROUND_SCREEN), true) LOCAL_CFLAGS += -DTW_ROUND_SCREEN endif +ifeq ($(TW_SCREEN_BLANK_ON_BOOT), true) + LOCAL_CFLAGS += -DTW_SCREEN_BLANK_ON_BOOT +endif +ifeq ($(TW_EXCLUDE_NANO), true) + LOCAL_CFLAGS += -DTW_EXCLUDE_NANO +endif +ifeq ($(AB_OTA_UPDATER),true) + LOCAL_CFLAGS += -DAB_OTA_UPDATER=1 +endif +ifeq ($(TW_BOOT_MENU), true) + LOCAL_CFLAGS += -DTW_BOOT_MENU +endif LOCAL_C_INCLUDES += \ bionic \ + system/core/base/include \ system/core/include \ system/core/libpixelflinger/include diff --git a/gui/action.cpp b/gui/action.cpp index 0216d849e2..980f73db90 100755 --- a/gui/action.cpp +++ b/gui/action.cpp @@ -38,6 +38,7 @@ #include #include "../partitions.hpp" #include "../twrp-functions.hpp" +#include "../twrpRepacker.hpp" #include "../openrecoveryscript.hpp" #include "../adb_install.h" @@ -63,6 +64,8 @@ std::set GUIAction::setActionsRunningInCallerThread; static string zip_queue[10]; static int zip_queue_index; pid_t sideload_child_pid; +extern std::vector Users_List; +extern GUITerminal* term; static void *ActionThread_work_wrapper(void *data); @@ -199,6 +202,10 @@ GUIAction::GUIAction(xml_node<>* node) ADD_ACTION(setlanguage); ADD_ACTION(checkforapp); ADD_ACTION(togglebacklight); + ADD_ACTION(changeterminal); +#ifdef TW_BOOT_MENU + ADD_ACTION(nonthreadedcmd); +#endif // remember actions that run in the caller thread for (mapFunc::const_iterator it = mf.begin(); it != mf.end(); ++it) @@ -233,7 +240,15 @@ GUIAction::GUIAction(xml_node<>* node) ADD_ACTION(installapp); ADD_ACTION(uninstalltwrpsystemapp); ADD_ACTION(repackimage); + ADD_ACTION(reflashtwrp); ADD_ACTION(fixabrecoverybootloop); + ADD_ACTION(applycustomtwrpfolder); +#ifndef TW_EXCLUDE_NANO + ADD_ACTION(editfile); +#endif +#ifdef TW_BOOT_MENU + ADD_ACTION(threadedsleepcounter); +#endif } // First, get the action @@ -369,6 +384,8 @@ int GUIAction::flash_zip(std::string filename, int* wipe_cache) int ret_val = 0; DataManager::SetValue("ui_progress", 0); + DataManager::SetValue("ui_portion_size", 0); + DataManager::SetValue("ui_portion_start", 0); if (filename.empty()) { @@ -389,7 +406,7 @@ int GUIAction::flash_zip(std::string filename, int* wipe_cache) if (simulate) { simulate_progress_bar(); } else { - ret_val = TWinstall_zip(filename.c_str(), wipe_cache); + ret_val = TWinstall_zip(filename.c_str(), wipe_cache, (bool) !DataManager::GetIntValue(TW_SKIP_DIGEST_CHECK_ZIP_VAR)); // Now, check if we need to ensure TWRP remains installed... struct stat st; @@ -408,6 +425,8 @@ int GUIAction::flash_zip(std::string filename, int* wipe_cache) // Done DataManager::SetValue("ui_progress", 100); DataManager::SetValue("ui_progress", 0); + DataManager::SetValue("ui_portion_size", 0); + DataManager::SetValue("ui_portion_start", 0); return ret_val; } @@ -490,10 +509,12 @@ void GUIAction::operation_start(const string operation_name) time(&Start); DataManager::SetValue(TW_ACTION_BUSY, 1); DataManager::SetValue("ui_progress", 0); + DataManager::SetValue("ui_portion_size", 0); + DataManager::SetValue("ui_portion_start", 0); DataManager::SetValue("tw_operation", operation_name); DataManager::SetValue("tw_operation_state", 0); DataManager::SetValue("tw_operation_status", 0); - bool tw_ab_device = TWFunc::get_cache_dir() != NON_AB_CACHE_DIR; + bool tw_ab_device = TWFunc::get_log_dir() != CACHE_LOGS_DIR; DataManager::SetValue("tw_ab_device", tw_ab_device); } @@ -654,8 +675,10 @@ int GUIAction::copylog(std::string arg __unused) { string dst, curr_storage; int copy_kernel_log = 0; + int copy_logcat = 1; DataManager::GetValue("tw_include_kernel_log", copy_kernel_log); + DataManager::GetValue("tw_include_logcat", copy_logcat); PartitionManager.Mount_Current_Storage(true); curr_storage = DataManager::GetCurrentStoragePath(); dst = curr_storage + "/recovery.log"; @@ -663,6 +686,8 @@ int GUIAction::copylog(std::string arg __unused) tw_set_default_metadata(dst.c_str()); if (copy_kernel_log) TWFunc::copy_kernel_log(curr_storage); + if (copy_logcat) + TWFunc::copy_logcat(curr_storage); sync(); gui_msg(Msg("copy_log=Copied recovery log to {1}")(dst)); } else @@ -816,6 +841,13 @@ int GUIAction::sleepcounter(std::string arg) return 0; } +#ifdef TW_BOOT_MENU +int GUIAction::threadedsleepcounter(std::string arg) +{ + return sleepcounter(arg); +} +#endif + int GUIAction::appenddatetobackupname(std::string arg __unused) { operation_start("AppendDateToBackupName"); @@ -1022,6 +1054,17 @@ void GUIAction::reinject_after_flash() } } +int GUIAction::ozip_decrypt(string zip_path) +{ + if (!TWFunc::Path_Exists("/sbin/ozip_decrypt")) { + return 1; + } + gui_msg("ozip_decrypt_decryption=Starting Ozip Decryption..."); + TWFunc::Exec_Cmd("ozip_decrypt " + (string)TW_OZIP_DECRYPT_KEY + " '" + zip_path + "'"); + gui_msg("ozip_decrypt_finish=Ozip Decryption Finished!"); + return 0; +} + int GUIAction::flash(std::string arg) { int i, ret_val = 0, wipe_cache = 0; @@ -1032,6 +1075,20 @@ int GUIAction::flash(std::string arg) size_t slashpos = zip_path.find_last_of('/'); string zip_filename = (slashpos == string::npos) ? zip_path : zip_path.substr(slashpos + 1); operation_start("Flashing"); + if((zip_path.substr(zip_path.size() - 4, 4)) == "ozip") + { + if((ozip_decrypt(zip_path)) != 0) + { + LOGERR("Unable to find ozip_decrypt!"); + break; + } + zip_filename = (zip_filename.substr(0, zip_filename.size() - 4)).append("zip"); + zip_path = (zip_path.substr(0, zip_path.size() - 4)).append("zip"); + if (!TWFunc::Path_Exists(zip_path)) { + LOGERR("Unable to find decrypted zip"); + break; + } + } DataManager::SetValue("tw_filename", zip_path); DataManager::SetValue("tw_file", zip_filename); DataManager::SetValue(TW_ZIP_INDEX, (i + 1)); @@ -1373,6 +1430,13 @@ int GUIAction::cmd(std::string arg) return 0; } +#ifdef TW_BOOT_MENU +int GUIAction::nonthreadedcmd(std::string arg) +{ + return cmd(arg); +} +#endif + int GUIAction::terminalcommand(std::string arg) { int op_status = 0; @@ -1495,12 +1559,31 @@ int GUIAction::decrypt(std::string arg __unused) simulate_progress_bar(); } else { string Password; + string userID; DataManager::GetValue("tw_crypto_password", Password); - op_status = PartitionManager.Decrypt_Device(Password); + + if (DataManager::GetIntValue(TW_IS_FBE)) { // for FBE + DataManager::GetValue("tw_crypto_user_id", userID); + if (userID != "") { + op_status = PartitionManager.Decrypt_Device(Password, atoi(userID.c_str())); + if (userID != "0") { + if (op_status != 0) + op_status = 1; + operation_end(op_status); + return 0; + } + } else { + LOGINFO("User ID not found\n"); + op_status = 1; + } + ::sleep(1); + } else { // for FDE + op_status = PartitionManager.Decrypt_Device(Password); + } + if (op_status != 0) op_status = 1; else { - DataManager::SetValue(TW_IS_ENCRYPTED, 0); int has_datamedia; @@ -1760,16 +1843,41 @@ int GUIAction::stopmtp(std::string arg __unused) int GUIAction::flashimage(std::string arg __unused) { int op_status = 0; + bool flag = true; operation_start("Flash Image"); string path, filename; DataManager::GetValue("tw_zip_location", path); DataManager::GetValue("tw_file", filename); - if (PartitionManager.Flash_Image(path, filename)) - op_status = 0; // success - else - op_status = 1; // fail +#ifdef AB_OTA_UPDATER + string target = DataManager::GetStrValue("tw_flash_partition"); + unsigned int pos = target.find_last_of(';'); + string mount_point = pos != string::npos ? target.substr(0, pos) : ""; + TWPartition* t_part = PartitionManager.Find_Partition_By_Path(mount_point); + bool flash_in_both_slots = DataManager::GetIntValue("tw_flash_both_slots") ? true : false; + + if (t_part != NULL && (flash_in_both_slots && t_part->SlotSelect)) + { + string current_slot = PartitionManager.Get_Active_Slot_Display(); + bool pre_op_status = PartitionManager.Flash_Image(path, filename); + + PartitionManager.Set_Active_Slot(current_slot == "A" ? "B" : "A"); + op_status = (int) !(pre_op_status && PartitionManager.Flash_Image(path, filename)); + PartitionManager.Set_Active_Slot(current_slot); + + DataManager::SetValue("tw_flash_both_slots", 0); + flag = false; + } +#endif + if (flag) + { + if (PartitionManager.Flash_Image(path, filename)) + op_status = 0; // success + else + op_status = 1; // fail + } + operation_end(op_status); return 0; } @@ -1894,9 +2002,11 @@ int GUIAction::togglebacklight(std::string arg __unused) int GUIAction::setbootslot(std::string arg) { operation_start("Set Boot Slot"); - if (!simulate) + if (!simulate) { + if (PartitionManager.Find_Partition_By_Path("/vendor")) + PartitionManager.UnMount_By_Path("/vendor",true); PartitionManager.Set_Active_Slot(arg); - else + } else simulate_progress_bar(); operation_end(0); return 0; @@ -1907,48 +2017,10 @@ int GUIAction::checkforapp(std::string arg __unused) operation_start("Check for TWRP App"); if (!simulate) { - string sdkverstr = TWFunc::System_Property_Get("ro.build.version.sdk"); - int sdkver = 0; - if (!sdkverstr.empty()) { - sdkver = atoi(sdkverstr.c_str()); - } - if (sdkver <= 13) { - if (sdkver == 0) - LOGINFO("Unable to read sdk version from build prop\n"); - else - LOGINFO("SDK version too low for TWRP app (%i < 14)\n", sdkver); - DataManager::SetValue("tw_app_install_status", 1); // 0 = no status, 1 = not installed, 2 = already installed or do not install - goto exit; - } - if (TWFunc::Is_TWRP_App_In_System()) { - DataManager::SetValue("tw_app_install_status", 2); // 0 = no status, 1 = not installed, 2 = already installed or do not install - goto exit; - } - if (PartitionManager.Mount_By_Path("/data", false)) { - const char parent_path[] = "/data/app"; - const char app_prefix[] = "me.twrp.twrpapp-"; - DIR *d = opendir(parent_path); - if (d) { - struct dirent *p; - while ((p = readdir(d))) { - if (p->d_type != DT_DIR || strlen(p->d_name) < strlen(app_prefix) || strncmp(p->d_name, app_prefix, strlen(app_prefix))) - continue; - closedir(d); - LOGINFO("App found at '%s/%s'\n", parent_path, p->d_name); - DataManager::SetValue("tw_app_install_status", 2); // 0 = no status, 1 = not installed, 2 = already installed or do not install - goto exit; - } - closedir(d); - } - } else { - LOGINFO("Data partition cannot be mounted during app check\n"); - DataManager::SetValue("tw_app_install_status", 2); // 0 = no status, 1 = not installed, 2 = already installed or do not install - } + TWFunc::checkforapp(); } else simulate_progress_bar(); - LOGINFO("App not installed\n"); - DataManager::SetValue("tw_app_install_status", 1); // 0 = no status, 1 = not installed, 2 = already installed -exit: + operation_end(0); return 0; } @@ -2032,6 +2104,22 @@ int GUIAction::installapp(std::string arg __unused) LOGERR("setfilecon %s error: %s\n", install_path.c_str(), strerror(errno)); goto exit; } + + // System apps require their permissions to be pre-set via an XML file in /etc/permissions + string permission_path = base_path + "/etc/permissions/privapp-permissions-twrpapp.xml"; + if (TWFunc::copy_file("/sbin/privapp-permissions-twrpapp.xml", permission_path, 0644)) { + LOGERR("Error copying permission file\n"); + goto exit; + } + if (chown(permission_path.c_str(), 1000, 1000)) { + LOGERR("chown %s error: %s\n", permission_path.c_str(), strerror(errno)); + goto exit; + } + if (setfilecon(permission_path.c_str(), (security_context_t)context.c_str()) < 0) { + LOGERR("setfilecon %s error: %s\n", permission_path.c_str(), strerror(errno)); + goto exit; + } + sync(); sync(); PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), true); @@ -2045,6 +2133,7 @@ int GUIAction::installapp(std::string arg __unused) } else simulate_progress_bar(); exit: + TWFunc::checkforapp(); operation_end(0); return 0; } @@ -2098,6 +2187,7 @@ int GUIAction::uninstalltwrpsystemapp(std::string arg __unused) } else simulate_progress_bar(); exit: + TWFunc::checkforapp(); operation_end(0); return 0; } @@ -2105,6 +2195,8 @@ int GUIAction::uninstalltwrpsystemapp(std::string arg __unused) int GUIAction::repackimage(std::string arg __unused) { int op_status = 1; + twrpRepacker repacker; + operation_start("Repack Image"); if (!simulate) { @@ -2117,7 +2209,7 @@ int GUIAction::repackimage(std::string arg __unused) Repack_Options.Type = REPLACE_KERNEL; else Repack_Options.Type = REPLACE_RAMDISK; - if (!PartitionManager.Repack_Images(path, Repack_Options)) + if (!repacker.Repack_Image_And_Flash(path, Repack_Options)) goto exit; } else simulate_progress_bar(); @@ -2127,9 +2219,28 @@ int GUIAction::repackimage(std::string arg __unused) return 0; } +int GUIAction::reflashtwrp(std::string arg __unused) +{ + int op_status = 1; + twrpRepacker repacker; + + operation_start("Repack Image"); + if (!simulate) + { + if (!repacker.Flash_Current_Twrp()) + goto exit; + } else + simulate_progress_bar(); + op_status = 0; +exit: + operation_end(op_status); + return 0; +} int GUIAction::fixabrecoverybootloop(std::string arg __unused) { int op_status = 1; + twrpRepacker repacker; + operation_start("Repack Image"); if (!simulate) { @@ -2145,11 +2256,11 @@ int GUIAction::fixabrecoverybootloop(std::string arg __unused) gui_msg(Msg(msg::kError, "unable_to_locate=Unable to locate {1}.")("/boot")); goto exit; } - if (!PartitionManager.Prepare_Repack(part, REPACK_ORIG_DIR, DataManager::GetIntValue("tw_repack_backup_first") != 0, gui_lookup("repack", "Repack"))) + if (!repacker.Backup_Image_For_Repack(part, REPACK_ORIG_DIR, DataManager::GetIntValue("tw_repack_backup_first") != 0, gui_lookup("repack", "Repack"))) goto exit; DataManager::SetProgress(.25); gui_msg("fixing_recovery_loop_patch=Patching kernel..."); - std::string command = "cd " REPACK_ORIG_DIR " && /sbin/magiskboot --hexpatch kernel 77616E745F696E697472616D667300 736B69705F696E697472616D667300"; + std::string command = "cd " REPACK_ORIG_DIR " && /sbin/magiskboot hexpatch kernel 77616E745F696E697472616D667300 736B69705F696E697472616D667300"; if (TWFunc::Exec_Cmd(command) != 0) { gui_msg(Msg(msg::kError, "fix_recovery_loop_patch_error=Error patching kernel.")); goto exit; @@ -2165,7 +2276,7 @@ int GUIAction::fixabrecoverybootloop(std::string arg __unused) } DataManager::SetProgress(.5); gui_msg(Msg("repacking_image=Repacking {1}...")(part->Display_Name)); - command = "cd " REPACK_ORIG_DIR " && /sbin/magiskboot --repack " REPACK_ORIG_DIR "boot.img"; + command = "cd " REPACK_ORIG_DIR " && /sbin/magiskboot repack " REPACK_ORIG_DIR "boot.img"; if (TWFunc::Exec_Cmd(command) != 0) { gui_msg(Msg(msg::kError, "repack_error=Error repacking image.")); goto exit; @@ -2187,3 +2298,81 @@ int GUIAction::fixabrecoverybootloop(std::string arg __unused) operation_end(op_status); return 0; } + +int GUIAction::changeterminal(std::string arg) { + bool res = true; + std::string resp, cmd = "cd " + arg; + DataManager::GetValue("tw_terminal_location", resp); + if (arg.empty() && !resp.empty()) { + cmd = "cd /"; + for (uint8_t iter = 0; iter < cmd.size(); iter++) + term->NotifyCharInput(cmd.at(iter)); + term->NotifyCharInput(13); + DataManager::SetValue("tw_terminal_location", ""); + return 0; + } + if (term != NULL && !arg.empty()) { + DataManager::SetValue("tw_terminal_location", arg); + if (term->status()) { + for (uint8_t iter = 0; iter < cmd.size(); iter++) + term->NotifyCharInput(cmd.at(iter)); + term->NotifyCharInput(13); + } + else if (chdir(arg.c_str()) != 0) { + LOGINFO("Unable to change dir to %s\n", arg.c_str()); + res = false; + } + } + else { + res = false; + LOGINFO("Unable to switch to Terminal\n"); + } + if (res) + gui_changePage("terminalcommand"); + return 0; +} +#ifndef TW_EXCLUDE_NANO +int GUIAction::editfile(std::string arg) { + if (term != NULL) { + for (uint8_t iter = 0; iter < arg.size(); iter++) + term->NotifyCharInput(arg.at(iter)); + term->NotifyCharInput(13); + } + else + LOGINFO("Unable to switch to Terminal\n"); + return 0; +} +#endif + +int GUIAction::applycustomtwrpfolder(string arg __unused) +{ + operation_start("ChangingTWRPFolder"); + string storageFolder = DataManager::GetSettingsStoragePath(); + string newFolder = storageFolder + '/' + arg; + string newBackupFolder = newFolder + "/BACKUPS/" + DataManager::GetStrValue("device_id"); + string prevFolder = storageFolder + DataManager::GetStrValue(TW_RECOVERY_FOLDER_VAR); + bool ret = false; + + if (TWFunc::Path_Exists(newFolder)) { + gui_msg(Msg(msg::kError, "tw_folder_exists=A folder with that name already exists!")); + } else { + ret = true; + } + + if (newFolder != prevFolder && ret) { + ret = TWFunc::Exec_Cmd("mv -f \"" + prevFolder + "\" \"" + newFolder + '\"') != 0 ? false : true; + } else { + gui_msg(Msg(msg::kError, "tw_folder_exists=A folder with that name already exists!")); + } + + if (ret) ret = TWFunc::Recursive_Mkdir(newBackupFolder) ? true : false; + + + if (ret) { + DataManager::SetValue(TW_RECOVERY_FOLDER_VAR, '/' + arg); + DataManager::SetValue(TW_BACKUPS_FOLDER_VAR, newBackupFolder); + DataManager::mBackingFile = newFolder + '/' + TW_SETTINGS_FILE; + } + operation_end((int)!ret); + return 0; +} diff --git a/gui/blanktimer.hpp b/gui/blanktimer.hpp index fe7b77c174..6aca270878 100644 --- a/gui/blanktimer.hpp +++ b/gui/blanktimer.hpp @@ -42,10 +42,11 @@ class blanktimer bool isScreenOff(); + void blank(void); + private: void setTimer(void); string getBrightness(void); - void blank(void); pthread_mutex_t mutex; enum State { kOn = 0, kDim = 1, kOff = 2, kBlanked = 3 }; diff --git a/gui/fileselector.cpp b/gui/fileselector.cpp index fe378c8482..a32743a584 100644 --- a/gui/fileselector.cpp +++ b/gui/fileselector.cpp @@ -20,7 +20,15 @@ #include #include #include - +#ifdef __ANDROID_API_M__ +#include +#ifdef __ANDROID_API_N__ +#include +#else +#include +#endif +#else +#endif extern "C" { #include "../twcommon.h" } @@ -61,6 +69,12 @@ GUIFileSelector::GUIFileSelector(xml_node<>* node) : GUIScrollList(node) if (attr) mShowNavFolders = atoi(attr->value()); } + child = FindNode(node, "prfxfilter"); + if (child) { + attr = child->first_attribute("prfx"); + if (attr) + mPrfx = attr->value(); + } // Handle the path variable child = FindNode(node, "path"); @@ -253,6 +267,7 @@ int GUIFileSelector::GetFileList(const std::string folder) while ((de = readdir(d)) != NULL) { FileData data; + bool match = false; data.fileName = de->d_name; if (data.fileName == ".") @@ -279,11 +294,57 @@ int GUIFileSelector::GetFileList(const std::string folder) if (mShowNavFolders || (data.fileName != "." && data.fileName != "..")) mFolderList.push_back(data); } else if (data.fileType == DT_REG || data.fileType == DT_LNK || data.fileType == DT_BLK) { - if (mExtn.empty() || (data.fileName.length() > mExtn.length() && data.fileName.substr(data.fileName.length() - mExtn.length()) == mExtn)) { - if (mExtn == ".ab" && twadbbu::Check_ADB_Backup_File(path)) +#ifdef __ANDROID_API_M__ + std::vector mExtnResults = android::base::Split(mExtn, ";"); + for (const std::string& mExtnElement : mExtnResults) + { + std::string mExtnName = android::base::Trim(mExtnElement); + if (mExtnName.empty() || (data.fileName.length() >= mExtnName.length() && data.fileName.substr(data.fileName.length() - mExtnName.length()) == mExtnName)) { + if (mExtnName == ".ab" && twadbbu::Check_ADB_Backup_File(path)) + mFolderList.push_back(data); + else + mFileList.push_back(data); + match = true; + break; + } + } + + if (!match) { + std::vector mPrfxResults = android::base::Split(mPrfx, ";"); + for (const std::string& mPrfxElement : mPrfxResults) + { + std::string mPrfxName = android::base::Trim(mPrfxElement); + if (!mPrfxName.empty() && data.fileName.length() >= mPrfxName.length() && data.fileName.substr(0, mPrfxName.length()) == mPrfxName) { + mFileList.push_back(data); + } +#else //On android 5.1 we can't use android::base::Trim and Split so just use the first extension written in the list + std::size_t seppos = mExtn.find_first_of(";"); + std::string mExtnf; + if (seppos!=std::string::npos){ + mExtnf = mExtn.substr(0, seppos); + } else { + mExtnf = mExtn; + } + if (mExtnf.empty() || (data.fileName.length() >= mExtnf.length() && data.fileName.substr(data.fileName.length() - mExtnf.length()) == mExtnf)) { + if (mExtnf == ".ab" && twadbbu::Check_ADB_Backup_File(path)) mFolderList.push_back(data); else mFileList.push_back(data); + match = true; + } + + if (!match) { + std::size_t seppos = mPrfx.find_first_of(";"); + std::string mPrfxf; + if (seppos!=std::string::npos){ + mPrfxf = mPrfx.substr(0, seppos); + } else { + mPrfxf = mPrfx; + } + if (!mPrfxf.empty() && data.fileName.length() >= mPrfxf.length() && data.fileName.substr(0, mPrfxf.length()) == mPrfxf) { + mFileList.push_back(data); +#endif + } } } } diff --git a/gui/gui.cpp b/gui/gui.cpp index ce8c3e29d9..7d6066a2f4 100644 --- a/gui/gui.cpp +++ b/gui/gui.cpp @@ -91,9 +91,13 @@ static void flip(void) timespec time; clock_gettime(CLOCK_MONOTONIC, &time); write(gRecorder, &time, sizeof(timespec)); +#ifndef TW_NO_SCREEN gr_write_frame_to_file(gRecorder); +#endif } +#ifndef TW_NO_SCREEN gr_flip(); +#endif } void rapidxml::parse_error_handler(const char *what, void *where) @@ -671,7 +675,9 @@ int gui_changePage(std::string newPage) { LOGINFO("Set page: '%s'\n", newPage.c_str()); PageManager::ChangePage(newPage); +#ifndef TW_NO_SCREEN gForceRender.set_value(1); +#endif return 0; } @@ -679,7 +685,9 @@ int gui_changeOverlay(std::string overlay) { LOGINFO("Set overlay: '%s'\n", overlay.c_str()); PageManager::ChangeOverlay(overlay); +#ifndef TW_NO_SCREEN gForceRender.set_value(1); +#endif return 0; } @@ -754,6 +762,12 @@ extern "C" int gui_init(void) gr_init(); TWFunc::Set_Brightness(DataManager::GetStrValue("tw_brightness")); +#ifdef TW_SCREEN_BLANK_ON_BOOT + printf("TW_SCREEN_BLANK_ON_BOOT := true\n"); + blankTimer.blank(); + blankTimer.resetTimerAndUnblank(); +#endif + // load and show splash screen if (PageManager::LoadPackage("splash", TWRES "splash.xml", "splash")) { LOGERR("Failed to load splash screen XML.\n"); @@ -765,6 +779,9 @@ extern "C" int gui_init(void) PageManager::ReleasePackage("splash"); } +#ifdef TW_DELAY_TOUCH_INIT_MS + usleep(TW_DELAY_TOUCH_INIT_MS); +#endif ev_init(); return 0; } @@ -858,10 +875,12 @@ extern "C" int gui_loadCustomResources(void) #endif return 0; +#ifndef TW_OEM_BUILD error: LOGERR("An internal error has occurred: unable to load theme.\n"); gGuiInitialized = 0; return -1; +#endif } extern "C" int gui_start(void) @@ -869,7 +888,27 @@ extern "C" int gui_start(void) return gui_startPage("main", 1, 0); } -extern "C" int gui_startPage(const char *page_name, const int allow_commands, int stop_on_page_done) +#ifdef TW_BOOT_MENU +extern "C" void boot_menu() +{ + // load and show bootmenu screen + if (PageManager::LoadPackage("bootmenu", TWRES "bootmenu.xml", "bootmenu")) { + LOGERR("Failed to load bootmenu screen XML.\n"); + } + else { + TWPartition* partition = PartitionManager.Find_Partition_By_Path("/misc"); + const char* misc_dev = partition?partition->Actual_Block_Device.c_str():""; + PageManager::SelectPackage("bootmenu"); + input_handler.init(); + DataManager::SetValue("bm_loaded", "1"); + DataManager::SetValue("misc_dev", misc_dev); + runPages("bootmenu", 0); + } + +} +#endif + +extern "C" int gui_startPage(const char *page_name, __attribute__((unused)) const int allow_commands, int stop_on_page_done) { if (!gGuiInitialized) return -1; diff --git a/gui/gui.h b/gui/gui.h index 034f1cd921..c6d92ec015 100644 --- a/gui/gui.h +++ b/gui/gui.h @@ -29,6 +29,9 @@ int gui_startPage(const char* page_name, const int allow_comands, int stop_on_pa void gui_print(const char *fmt, ...); void gui_print_color(const char *color, const char *fmt, ...); void gui_set_FILE(FILE* f); +#ifdef TW_BOOT_MENU +void boot_menu(); +#endif void set_scale_values(float w, float h); int scale_theme_x(int initial_x); diff --git a/gui/gui.hpp b/gui/gui.hpp index d5b9553d69..7e4ee4ea89 100644 --- a/gui/gui.hpp +++ b/gui/gui.hpp @@ -28,6 +28,7 @@ void gui_warn(const char* text); void gui_err(const char* text); void gui_highlight(const char* text); void gui_msg(Message msg); +void gui_err(Message msg); std::string gui_parse_text(std::string inText); std::string gui_lookup(const std::string& resource_name, const std::string& default_value); diff --git a/gui/listbox.cpp b/gui/listbox.cpp index 9fbe09234d..3386465e29 100644 --- a/gui/listbox.cpp +++ b/gui/listbox.cpp @@ -26,6 +26,7 @@ extern "C" { #include "rapidxml.hpp" #include "objects.hpp" #include "../data.hpp" +#include "../partitions.hpp" #include "pages.hpp" extern std::vector Language_List; @@ -82,10 +83,28 @@ GUIListBox::GUIListBox(xml_node<>* node) : GUIScrollList(node) data.selected = 0; mListItems.push_back(data); } + } else if (mVariable == "tw_crypto_user_id") { + std::vector::iterator iter; + std::vector* Users_List = PartitionManager.Get_Users_List(); + for (iter = Users_List->begin(); iter != Users_List->end(); iter++) { + if (!(*iter).isDecrypted) { + ListItem data; + data.displayName = (*iter).userName; + data.variableValue = (*iter).userId; + data.action = NULL; + DataManager::GetValue("tw_crypto_user_id", currentValue); + if (currentValue == (*iter).userId || currentValue == "") { + data.selected = 1; + DataManager::SetValue("tw_crypto_user_id", (*iter).userId); + DataManager::SetValue("tw_crypto_pwtype", (*iter).type); + } else + data.selected = 0; + mListItems.push_back(data); + } + } } - } - else - allowSelection = false; // allows using listbox as a read-only list or menu + } else + allowSelection = false; // allows using listbox as a read-only list or menu // Get the data for the list child = FindNode(node, "listitem"); @@ -94,16 +113,14 @@ GUIListBox::GUIListBox(xml_node<>* node) : GUIScrollList(node) ListItem item; attr = child->first_attribute("name"); - if (!attr) - continue; + if (!attr) continue; // We will parse display names when we get page focus to ensure that translating takes place item.displayName = attr->value(); item.variableValue = gui_parse_text(child->value()); item.selected = (child->value() == currentValue); item.action = NULL; xml_node<>* action = child->first_node("action"); - if (!action) - action = child->first_node("actions"); + if (!action) action = child->first_node("actions"); if (action) { item.action = new GUIAction(child); allowSelection = true; @@ -122,7 +139,7 @@ GUIListBox::GUIListBox(xml_node<>* node) : GUIScrollList(node) LoadConditions(child, item.mConditions); mListItems.push_back(item); - mVisibleItems.push_back(mListItems.size()-1); + mVisibleItems.push_back(mListItems.size() - 1); child = child->next_sibling("listitem"); } @@ -137,6 +154,33 @@ int GUIListBox::Update(void) if (!isConditionTrue()) return 0; + if (mVariable == "tw_crypto_user_id") { + mListItems.clear(); + std::vector::iterator iter; + std::vector* Users_List = PartitionManager.Get_Users_List(); + for (iter = Users_List->begin(); iter != Users_List->end(); iter++) { + if (!(*iter).isDecrypted) { + ListItem data; + data.displayName = (*iter).userName; + data.variableValue = (*iter).userId; + data.action = NULL; + DataManager::GetValue("tw_crypto_user_id", currentValue); + if (currentValue == (*iter).userId || currentValue == "") { + data.selected = 1; + DataManager::SetValue("tw_crypto_user_id", (*iter).userId); + DataManager::SetValue("tw_crypto_pwtype", (*iter).type); + } else + data.selected = 0; + mListItems.push_back(data); + } + } + mVisibleItems.clear(); + for (size_t i = 0; i < mListItems.size(); i++) { + mVisibleItems.push_back(i); + } + mUpdate = 1; + } + GUIScrollList::Update(); if (mUpdate) { diff --git a/gui/objects.hpp b/gui/objects.hpp index 3f7241831f..02c5ae4100 100644 --- a/gui/objects.hpp +++ b/gui/objects.hpp @@ -288,6 +288,7 @@ class GUIAction : public GUIObject, public ActionObject ThreadType getThreadType(const Action& action); void simulate_progress_bar(void); int flash_zip(std::string filename, int* wipe_cache); + int ozip_decrypt(std::string zip_path); void reinject_after_flash(); void operation_start(const string operation_name); void operation_end(const int operation_status); @@ -327,6 +328,9 @@ class GUIAction : public GUIObject, public ActionObject int screenshot(std::string arg); int setbrightness(std::string arg); int checkforapp(std::string arg); +#ifdef TW_BOOT_MENU + int nonthreadedcmd(std::string arg); +#endif // (originally) threaded actions int fileexists(std::string arg); @@ -369,7 +373,16 @@ class GUIAction : public GUIObject, public ActionObject int installapp(std::string arg); int uninstalltwrpsystemapp(std::string arg); int repackimage(std::string arg); + int reflashtwrp(std::string arg); int fixabrecoverybootloop(std::string arg); + int changeterminal(std::string arg); +#ifndef TW_EXCLUDE_NANO + int editfile(std::string arg); +#endif +#ifdef TW_BOOT_MENU + int threadedsleepcounter(std::string arg); +#endif + int applycustomtwrpfolder(std::string arg); int simulate; }; @@ -606,6 +619,7 @@ class GUIFileSelector : public GUIScrollList std::string mPathVar; // current path displayed, saved in the data manager std::string mPathDefault; // default value for the path if none is set in mPathVar std::string mExtn; // used for filtering the file list, for example, *.zip + std::string mPrfx; // used for filtering the file list, for example, Magisk- std::string mVariable; // set when the user selects an item, pull path like /path/to/foo std::string mSortVariable; // data manager variable used to change the sorting of files std::string mSelection; // set when the user selects an item without the full path like selecting /path/to/foo would just be set to foo @@ -804,6 +818,8 @@ class GUITerminal : public GUIScrollList, public InputObject virtual size_t GetItemCount(); virtual void RenderItem(size_t itemindex, int yPos, bool selected); virtual void NotifySelect(size_t item_selected); + bool status(); + void stop(); protected: void InitAndResize(); diff --git a/gui/pages.cpp b/gui/pages.cpp index fd0ad9bf38..291abc457f 100644 --- a/gui/pages.cpp +++ b/gui/pages.cpp @@ -56,12 +56,12 @@ extern "C" { #include "objects.hpp" #include "blanktimer.hpp" -// version 2 requires theme to handle power button as action togglebacklight -#define TW_THEME_VERSION 3 +#include "../variables.h" #define TW_THEME_VER_ERR -2 extern int gGuiRunning; +GUITerminal* term = NULL; std::map PageManager::mPageSets; PageSet* PageManager::mCurrentSet; @@ -288,17 +288,20 @@ Page::Page(xml_node<>* page, std::vector*> *templates) { mTouchStart = NULL; +#ifndef TW_NO_SCREEN // We can memset the whole structure, because the alpha channel is ignored memset(&mBackground, 0, sizeof(COLOR)); - +#endif // With NULL, we make a console-only display if (!page) { +#ifndef TW_NO_SCREEN mName = "console"; GUIConsole* element = new GUIConsole(NULL); mRenders.push_back(element); mActions.push_back(element); +#endif return; } @@ -335,7 +338,9 @@ bool Page::ProcessNode(xml_node<>* page, std::vector*> *templates, in std::string type = child->name(); if (type == "background") { +#ifndef TW_NO_SCREEN mBackground = LoadAttrColor(child, "color", COLOR(0,0,0,0)); +#endif continue; } @@ -347,11 +352,14 @@ bool Page::ProcessNode(xml_node<>* page, std::vector*> *templates, in if (type == "text") { +#ifndef TW_NO_SCREEN GUIText* element = new GUIText(child); mObjects.push_back(element); mRenders.push_back(element); mActions.push_back(element); +#endif } +#ifndef TW_NO_SCREEN else if (type == "image") { GUIImage* element = new GUIImage(child); @@ -364,12 +372,14 @@ bool Page::ProcessNode(xml_node<>* page, std::vector*> *templates, in mObjects.push_back(element); mRenders.push_back(element); } +#endif else if (type == "action") { GUIAction* element = new GUIAction(child); mObjects.push_back(element); mActions.push_back(element); } +#ifndef TW_NO_SCREEN else if (type == "console") { GUIConsole* element = new GUIConsole(child); @@ -384,6 +394,7 @@ bool Page::ProcessNode(xml_node<>* page, std::vector*> *templates, in mRenders.push_back(element); mActions.push_back(element); mInputs.push_back(element); + term = element; } else if (type == "button") { @@ -518,12 +529,15 @@ bool Page::ProcessNode(xml_node<>* page, std::vector*> *templates, in { LOGERR("Unknown object type: %s.\n", type.c_str()); } +#endif } return true; } int Page::Render(void) { + +#ifndef TW_NO_SCREEN // Render background gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha); gr_fill(0, 0, gr_fb_width(), gr_fb_height()); @@ -535,6 +549,7 @@ int Page::Render(void) if ((*iter)->Render()) LOGERR("A render request has failed.\n"); } +#endif return 0; } @@ -542,6 +557,7 @@ int Page::Update(void) { int retCode = 0; +#ifndef TW_NO_SCREEN std::vector::iterator iter; for (iter = mRenders.begin(); iter != mRenders.end(); iter++) { @@ -551,6 +567,7 @@ int Page::Update(void) else if (ret > retCode) retCode = ret; } +#endif return retCode; } @@ -755,6 +772,7 @@ int PageSet::Load(LoadingContext& ctx, const std::string& filename) if (child) LoadVariables(child); + LOGINFO("Loading mouse cursor...\n"); child = root->first_node("mousecursor"); if (child) @@ -796,9 +814,11 @@ int PageSet::Load(LoadingContext& ctx, const std::string& filename) return rc; include = include->next_sibling("xmlfile"); + } } + return 0; } @@ -874,6 +894,7 @@ int PageSet::LoadDetails(LoadingContext& ctx, xml_node<>* root) gui_print_color("warning", "Stock theme version does not match TWRP version.\n"); } } + xml_node<>* resolution = child->first_node("resolution"); if (resolution) { LOGINFO("Checking resolution...\n"); @@ -898,6 +919,7 @@ int PageSet::LoadDetails(LoadingContext& ctx, xml_node<>* root) } } #endif +#ifndef TW_NO_SCREEN if (width != 0 && height != 0) { float scale_w = (((float)gr_fb_width() + (float)tw_w_offset) - ((float)offx * 2.0)) / (float)width; float scale_h = (((float)gr_fb_height() + (float)tw_h_offset) - ((float)offy * 2.0)) / (float)height; @@ -913,6 +935,7 @@ int PageSet::LoadDetails(LoadingContext& ctx, xml_node<>* root) set_scale_values(scale_w, scale_h); } } +#endif } else { LOGINFO("XML does not contain width and height, no scaling will be applied\n"); } @@ -1638,15 +1661,23 @@ xml_node<>* PageManager::FindStyle(std::string name) MouseCursor *PageManager::GetMouseCursor() { +#ifndef TW_NO_SCREEN if (!mMouseCursor) mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height()); +#else + mMouseCursor = new MouseCursor(0,0); +#endif return mMouseCursor; } void PageManager::LoadCursorData(xml_node<>* node) { if (!mMouseCursor) +#ifndef TW_NO_SCREEN mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height()); +#else + mMouseCursor = new MouseCursor(0, 0); +#endif mMouseCursor->LoadData(node); } diff --git a/gui/partitionlist.cpp b/gui/partitionlist.cpp index 16e09977ef..9c5b58e7d0 100644 --- a/gui/partitionlist.cpp +++ b/gui/partitionlist.cpp @@ -179,6 +179,8 @@ void GUIPartitionList::MatchList(void) { pos = variablelist.find(searchvalue); if (pos != string::npos) { mList.at(i).selected = 1; + TWPartition* t_part = PartitionManager.Find_Partition_By_Path(mList.at(i).Mount_Point); + DataManager::SetValue("tw_is_slot_part", t_part != NULL ? (int) t_part->SlotSelect : 0); } else { mList.at(i).selected = 0; } @@ -272,6 +274,8 @@ void GUIPartitionList::NotifySelect(size_t item_selected) mList.at(item_selected).selected = 0; else mList.at(item_selected).selected = 1; + TWPartition* t_part = PartitionManager.Find_Partition_By_Path(mList.at(item_selected).Mount_Point); + DataManager::SetValue("tw_is_slot_part", t_part != NULL ? (int) t_part->SlotSelect : 0); int i; string variablelist; diff --git a/gui/terminal.cpp b/gui/terminal.cpp index a4fed91047..79262eb2d0 100755 --- a/gui/terminal.cpp +++ b/gui/terminal.cpp @@ -46,7 +46,6 @@ extern "C" { #endif extern int g_pty_fd; // in gui.cpp where the select is - /* Pseudoterminal handler. */ @@ -142,7 +141,7 @@ class Pseudoterminal return -1; } int rc = ::write(fdMaster, buffer, size); - debug_printf("pty write: %d bytes -> %d\n", size, rc); + debug_printf("pty write: %zu bytes -> %d\n", size, rc); if (rc < 0) { LOGERR("pty write failed: %d\n", errno); // assume child has died @@ -386,6 +385,14 @@ class TerminalEngine output(buffer[i]); } + bool status() { + return pty.started(); + } + + void stop() { + pty.stop(); + } + void clear() { cursorX = cursorY = 0; @@ -899,6 +906,17 @@ void GUITerminal::NotifySelect(size_t item_selected __unused) // do nothing - terminal ignores selections } +bool GUITerminal::status() +{ + return engine->status(); +} + +void GUITerminal::stop() +{ + engine->stop(); + engine->clear(); +} + void GUITerminal::InitAndResize() { // make sure the shell is started diff --git a/gui/theme/common/landscape.xml b/gui/theme/common/landscape.xml index 8244c461ed..d02dce063a 100755 --- a/gui/theme/common/landscape.xml +++ b/gui/theme/common/landscape.xml @@ -175,6 +175,15 @@ + + + + + + + + + + + + + + + tw_sleep=%tw_sleep_total% + bootmenu2 + + + + + + + + + + + + diff --git a/gui/theme/landscape_mdpi/splash.xml b/gui/theme/landscape_mdpi/splash.xml index 74b6d177a6..ea87310d32 100644 --- a/gui/theme/landscape_mdpi/splash.xml +++ b/gui/theme/landscape_mdpi/splash.xml @@ -5,7 +5,7 @@ TeamWin TWRP splash screen - 3 + {themeversion} diff --git a/gui/theme/landscape_mdpi/ui.xml b/gui/theme/landscape_mdpi/ui.xml index 24458ec616..e06dba4d19 100755 --- a/gui/theme/landscape_mdpi/ui.xml +++ b/gui/theme/landscape_mdpi/ui.xml @@ -6,7 +6,7 @@ Backup Naowz Default basic theme preview.png - 3 + {themeversion} @@ -198,6 +198,7 @@ + @@ -718,5 +719,28 @@ + + diff --git a/gui/theme/portrait_hdpi/bootmenu.xml b/gui/theme/portrait_hdpi/bootmenu.xml new file mode 100644 index 0000000000..f5695e2a5b --- /dev/null +++ b/gui/theme/portrait_hdpi/bootmenu.xml @@ -0,0 +1,117 @@ + + +
+ + k4y0z + Boot Menu + boot menu + 3 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + tw_sleep=%tw_sleep_total% + bootmenu2 + + + + + + + + + + + +
diff --git a/gui/theme/portrait_mdpi/splash.xml b/gui/theme/portrait_mdpi/splash.xml index f8c695fdf9..b0b97ee5b8 100644 --- a/gui/theme/portrait_mdpi/splash.xml +++ b/gui/theme/portrait_mdpi/splash.xml @@ -5,7 +5,7 @@ TeamWin TWRP splash screen - 3 + {themeversion} diff --git a/gui/theme/portrait_mdpi/ui.xml b/gui/theme/portrait_mdpi/ui.xml index 8b91641ec8..9189df0c76 100755 --- a/gui/theme/portrait_mdpi/ui.xml +++ b/gui/theme/portrait_mdpi/ui.xml @@ -6,7 +6,7 @@ Backup Naowz Default basic theme preview.png - 3 + {themeversion} @@ -203,6 +203,7 @@ + @@ -637,5 +638,29 @@ + + diff --git a/gui/theme/watch_mdpi/splash.xml b/gui/theme/watch_mdpi/splash.xml index 62e8dc37b5..2ce71b385b 100644 --- a/gui/theme/watch_mdpi/splash.xml +++ b/gui/theme/watch_mdpi/splash.xml @@ -5,7 +5,7 @@ TeamWin TWRP splash screen - 3 + {themeversion} diff --git a/gui/theme/watch_mdpi/ui.xml b/gui/theme/watch_mdpi/ui.xml index 491de1c43c..ed7ac825c8 100644 --- a/gui/theme/watch_mdpi/ui.xml +++ b/gui/theme/watch_mdpi/ui.xml @@ -7,7 +7,7 @@ Backup Naowz Default basic theme preview.png - 3 + {themeversion} @@ -160,6 +160,7 @@ + @@ -387,5 +388,29 @@ + + diff --git a/installcommand.cpp b/installcommand.cpp index 99f4c5358c..022aef6763 100644 --- a/installcommand.cpp +++ b/installcommand.cpp @@ -121,12 +121,30 @@ static int check_newer_ab_build(ZipWrap* zip) } } char value[PROPERTY_VALUE_MAX]; + char propmodel[PROPERTY_VALUE_MAX]; + char propname[PROPERTY_VALUE_MAX]; property_get("ro.product.device", value, ""); + property_get("ro.product.model", propmodel, ""); + property_get("ro.product.name", propname, ""); const std::string& pkg_device = metadata["pre-device"]; - if (pkg_device != value || pkg_device.empty()) { + + std::vector assertResults = android::base::Split(pkg_device, ","); + + bool deviceExists = false; + + for(const std::string& deviceAssert : assertResults) + { + std::string assertName = android::base::Trim(deviceAssert); + if ((assertName == value || assertName == propmodel || assertName == propname ) && !assertName.empty()) { + deviceExists = true; + break; + } + } + + if (!deviceExists) { printf("Package is for product %s but expected %s\n", - pkg_device.c_str(), value); + pkg_device.c_str(), value); return INSTALL_ERROR; } diff --git a/libblkid/Android.mk b/libblkid/Android.mk index 42762e4e48..38a192f997 100644 --- a/libblkid/Android.mk +++ b/libblkid/Android.mk @@ -44,7 +44,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := libuuid LOCAL_MODULE_TAGS := optional #LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin -LOCAL_CFLAGS := -D_FILE_OFFSET_BITS=64 -DHAVE_LOFF_T -DHAVE_ERR_H -DHAVE_MEMPCPY -DHAVE_FSYNC +LOCAL_CFLAGS := -D_FILE_OFFSET_BITS=64 -DHAVE_LOFF_T -DHAVE_ERR_H -DHAVE_MEMPCPY -DHAVE_FSYNC -DHAVE_SYS_FILE_H LOCAL_CFLAGS += -Wno-missing-field-initializers -Wno-sign-compare -Wno-unused-parameter -Wno-format -Wno-pointer-arith LOCAL_SRC_FILES = libuuid/src/clear.c \ libuuid/src/copy.c \ diff --git a/microloader.h b/microloader.h new file mode 100644 index 0000000000..6d2c04d104 --- /dev/null +++ b/microloader.h @@ -0,0 +1,15 @@ +#ifdef TW_AMONET +#ifndef RECOVERY_AMONET_MICROLOADER_H_ +#define RECOVERY_AMONET_MICROLOADER_H_ + +#include + +#ifdef TW_MICROLOADER +extern uint8_t microloader_bin[1024]; +#else +uint8_t microloader_bin[1024]; +#endif + +#endif // RECOVERY_AMONET_MICROLOADER_H +#endif // TW_AMONET + diff --git a/minadbd21/Android.mk b/minadbd21/Android.mk index 201c795344..4bfc9b225e 100644 --- a/minadbd21/Android.mk +++ b/minadbd21/Android.mk @@ -28,4 +28,12 @@ LOCAL_MODULE_TAGS := eng LOCAL_MODULE := libminadbd LOCAL_C_INCLUDES += $(LOCAL_PATH)/../ LOCAL_SHARED_LIBRARIES := libfusesideload libcutils libc + + +ifeq ($(TW_IP_SIDELOAD), true) + LOCAL_SRC_FILES += transport_local.c + LOCAL_CFLAGS += -DTW_IP_SIDELOAD +endif + + include $(BUILD_SHARED_LIBRARY) diff --git a/minadbd21/adb.c b/minadbd21/adb.c index c35e8300b7..1604a03982 100644 --- a/minadbd21/adb.c +++ b/minadbd21/adb.c @@ -395,6 +395,18 @@ int adb_main(const char* path) usb_init(); } +#ifdef TW_IP_SIDELOAD + // Well not really, listen for network connections too. + char value[PROPERTY_VALUE_MAX]; + int port; + property_get("service.adb.tcp.port", value, ""); + if (sscanf(value, "%d", &port) == 1 && port > 0) { + printf("using port=%d\n", port); + // listen on TCP port specified by service.adb.tcp.port property + local_init(port); + } +#endif + /* Remove this so that perms work properly if (setgid(AID_SHELL) != 0) { fprintf(stderr, "failed to setgid to shell\n"); diff --git a/minadbd21/adb.h b/minadbd21/adb.h index 08ee989d6f..0dcb141e1b 100644 --- a/minadbd21/adb.h +++ b/minadbd21/adb.h @@ -244,6 +244,9 @@ void kick_transport( atransport* t ); #if ADB_HOST int get_available_local_transport_index(); #endif +#ifdef TW_IP_SIDELOAD +int init_socket_transport(atransport *t, int s, int port, int local); +#endif void init_usb_transport(atransport *t, usb_handle *usb, int state); /* for MacOS X cleanup */ diff --git a/minadbd21/transport.c b/minadbd21/transport.c index 92679f518a..9ea0beb84d 100644 --- a/minadbd21/transport.c +++ b/minadbd21/transport.c @@ -32,6 +32,13 @@ static atransport transport_list = { .prev = &transport_list, }; +#ifdef TW_IP_SIDELOAD +static atransport pending_list = { + .next = &pending_list, + .prev = &pending_list, +}; +#endif + ADB_MUTEX_DEFINE( transport_lock ); #if ADB_TRACE @@ -678,6 +685,52 @@ atransport *acquire_one_transport(int state, transport_type ttype, const char* s return result; } +#ifdef TW_IP_SIDELOAD +int register_socket_transport(int s, const char *serial, int port, int local) +{ + atransport *t = calloc(1, sizeof(atransport)); + atransport *n; + char buff[32]; + + if (!serial) { + snprintf(buff, sizeof buff, "T-%p", t); + serial = buff; + } + D("transport: %s init'ing for socket %d, on port %d\n", serial, s, port); + if (init_socket_transport(t, s, port, local) < 0) { + free(t); + return -1; + } + + adb_mutex_lock(&transport_lock); + for (n = pending_list.next; n != &pending_list; n = n->next) { + if (n->serial && !strcmp(serial, n->serial)) { + adb_mutex_unlock(&transport_lock); + free(t); + return -1; + } + } + + for (n = transport_list.next; n != &transport_list; n = n->next) { + if (n->serial && !strcmp(serial, n->serial)) { + adb_mutex_unlock(&transport_lock); + free(t); + return -1; + } + } + + t->next = &pending_list; + t->prev = pending_list.prev; + t->next->prev = t; + t->prev->next = t; + t->serial = strdup(serial); + adb_mutex_unlock(&transport_lock); + + register_transport(t); + return 0; +} +#endif + void register_usb_transport(usb_handle *usb, const char *serial, unsigned writeable) { atransport *t = calloc(1, sizeof(atransport)); diff --git a/minadbd21/transport_local.c b/minadbd21/transport_local.c new file mode 100644 index 0000000000..948cc15812 --- /dev/null +++ b/minadbd21/transport_local.c @@ -0,0 +1,444 @@ +/* + * Copyright (C) 2007 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 +#include +#include +#include + +#include "sysdeps.h" +#include +#if !ADB_HOST +#include +#endif + +#define TRACE_TAG TRACE_TRANSPORT +#include "adb.h" + +#ifdef HAVE_BIG_ENDIAN +#define H4(x) (((x) & 0xFF000000) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | (((x) & 0x000000FF) << 24) +static inline void fix_endians(apacket *p) +{ + p->msg.command = H4(p->msg.command); + p->msg.arg0 = H4(p->msg.arg0); + p->msg.arg1 = H4(p->msg.arg1); + p->msg.data_length = H4(p->msg.data_length); + p->msg.data_check = H4(p->msg.data_check); + p->msg.magic = H4(p->msg.magic); +} +#else +#define fix_endians(p) do {} while (0) +#endif + +#if ADB_HOST +/* we keep a list of opened transports. The atransport struct knows to which + * local transport it is connected. The list is used to detect when we're + * trying to connect twice to a given local transport. + */ +#define ADB_LOCAL_TRANSPORT_MAX 64 + +ADB_MUTEX_DEFINE( local_transports_lock ); + +static atransport* local_transports[ ADB_LOCAL_TRANSPORT_MAX ]; +#endif /* ADB_HOST */ + +static int remote_read(apacket *p, atransport *t) +{ + if(readx(t->sfd, &p->msg, sizeof(amessage))){ + D("remote local: read terminated (message)\n"); + return -1; + } + + fix_endians(p); + +#if 0 && defined HAVE_BIG_ENDIAN + D("read remote packet: %04x arg0=%0x arg1=%0x data_length=%0x data_check=%0x magic=%0x\n", + p->msg.command, p->msg.arg0, p->msg.arg1, p->msg.data_length, p->msg.data_check, p->msg.magic); +#endif + if(check_header(p)) { + D("bad header: terminated (data)\n"); + return -1; + } + + if(readx(t->sfd, p->data, p->msg.data_length)){ + D("remote local: terminated (data)\n"); + return -1; + } + + if(check_data(p)) { + D("bad data: terminated (data)\n"); + return -1; + } + + return 0; +} + +static int remote_write(apacket *p, atransport *t) +{ + int length = p->msg.data_length; + + fix_endians(p); + +#if 0 && defined HAVE_BIG_ENDIAN + D("write remote packet: %04x arg0=%0x arg1=%0x data_length=%0x data_check=%0x magic=%0x\n", + p->msg.command, p->msg.arg0, p->msg.arg1, p->msg.data_length, p->msg.data_check, p->msg.magic); +#endif + if(writex(t->sfd, &p->msg, sizeof(amessage) + length)) { + D("remote local: write terminated\n"); + return -1; + } + + return 0; +} + + +int local_connect(int port) { + return local_connect_arbitrary_ports(port-1, port); +} + +int local_connect_arbitrary_ports(int console_port, int adb_port) +{ + char buf[64]; + int fd = -1; + +#if ADB_HOST + const char *host = getenv("ADBHOST"); + if (host) { + fd = socket_network_client(host, adb_port, SOCK_STREAM); + } +#endif + if (fd < 0) { + fd = socket_loopback_client(adb_port, SOCK_STREAM); + } + + if (fd >= 0) { + D("client: connected on remote on fd %d\n", fd); + close_on_exec(fd); + disable_tcp_nagle(fd); + snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, console_port); + register_socket_transport(fd, buf, adb_port, 1); + return 0; + } + return -1; +} + + +static void *client_socket_thread(void *x) +{ +#if ADB_HOST + int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; + int count = ADB_LOCAL_TRANSPORT_MAX; + + D("transport: client_socket_thread() starting\n"); + + /* try to connect to any number of running emulator instances */ + /* this is only done when ADB starts up. later, each new emulator */ + /* will send a message to ADB to indicate that is is starting up */ + for ( ; count > 0; count--, port += 2 ) { + (void) local_connect(port); + } +#endif + return 0; +} + +static void *server_socket_thread(void * arg) +{ + int serverfd, fd; + struct sockaddr addr; + socklen_t alen; + int port = (int) (uintptr_t) arg; + + D("transport: server_socket_thread() starting\n"); + serverfd = -1; + for(;;) { + if(serverfd == -1) { + serverfd = socket_inaddr_any_server(port, SOCK_STREAM); + if(serverfd < 0) { + D("server: cannot bind socket yet\n"); + adb_sleep_ms(1000); + continue; + } + close_on_exec(serverfd); + } + + alen = sizeof(addr); + D("server: trying to get new connection from %d\n", port); + fd = adb_socket_accept(serverfd, &addr, &alen); + if(fd >= 0) { + D("server: new connection on fd %d\n", fd); + close_on_exec(fd); + disable_tcp_nagle(fd); + register_socket_transport(fd, "host", port, 1); + } + } + D("transport: server_socket_thread() exiting\n"); + return 0; +} + +/* This is relevant only for ADB daemon running inside the emulator. */ +#if !ADB_HOST +/* + * Redefine open and write for qemu_pipe.h that contains inlined references + * to those routines. We will redifine them back after qemu_pipe.h inclusion. + */ +#undef open +#undef write +#define open adb_open +#define write adb_write +#include +#undef open +#undef write +#define open ___xxx_open +#define write ___xxx_write + +/* A worker thread that monitors host connections, and registers a transport for + * every new host connection. This thread replaces server_socket_thread on + * condition that adbd daemon runs inside the emulator, and emulator uses QEMUD + * pipe to communicate with adbd daemon inside the guest. This is done in order + * to provide more robust communication channel between ADB host and guest. The + * main issue with server_socket_thread approach is that it runs on top of TCP, + * and thus is sensitive to network disruptions. For instance, the + * ConnectionManager may decide to reset all network connections, in which case + * the connection between ADB host and guest will be lost. To make ADB traffic + * independent from the network, we use here 'adb' QEMUD service to transfer data + * between the host, and the guest. See external/qemu/android/adb-*.* that + * implements the emulator's side of the protocol. Another advantage of using + * QEMUD approach is that ADB will be up much sooner, since it doesn't depend + * anymore on network being set up. + * The guest side of the protocol contains the following phases: + * - Connect with adb QEMUD service. In this phase a handle to 'adb' QEMUD service + * is opened, and it becomes clear whether or not emulator supports that + * protocol. + * - Wait for the ADB host to create connection with the guest. This is done by + * sending an 'accept' request to the adb QEMUD service, and waiting on + * response. + * - When new ADB host connection is accepted, the connection with adb QEMUD + * service is registered as the transport, and a 'start' request is sent to the + * adb QEMUD service, indicating that the guest is ready to receive messages. + * Note that the guest will ignore messages sent down from the emulator before + * the transport registration is completed. That's why we need to send the + * 'start' request after the transport is registered. + */ +static void *qemu_socket_thread(void * arg) +{ +/* 'accept' request to the adb QEMUD service. */ +static const char _accept_req[] = "accept"; +/* 'start' request to the adb QEMUD service. */ +static const char _start_req[] = "start"; +/* 'ok' reply from the adb QEMUD service. */ +static const char _ok_resp[] = "ok"; + + const int port = (int) (uintptr_t) arg; + int res, fd; + char tmp[256]; + char con_name[32]; + + D("transport: qemu_socket_thread() starting\n"); + + /* adb QEMUD service connection request. */ + snprintf(con_name, sizeof(con_name), "qemud:adb:%d", port); + + /* Connect to the adb QEMUD service. */ + fd = qemu_pipe_open(con_name); + if (fd < 0) { + /* This could be an older version of the emulator, that doesn't + * implement adb QEMUD service. Fall back to the old TCP way. */ + adb_thread_t thr; + D("adb service is not available. Falling back to TCP socket.\n"); + adb_thread_create(&thr, server_socket_thread, arg); + return 0; + } + + for(;;) { + /* + * Wait till the host creates a new connection. + */ + + /* Send the 'accept' request. */ + res = adb_write(fd, _accept_req, strlen(_accept_req)); + if ((size_t)res == strlen(_accept_req)) { + /* Wait for the response. In the response we expect 'ok' on success, + * or 'ko' on failure. */ + res = adb_read(fd, tmp, sizeof(tmp)); + if (res != 2 || memcmp(tmp, _ok_resp, 2)) { + D("Accepting ADB host connection has failed.\n"); + adb_close(fd); + } else { + /* Host is connected. Register the transport, and start the + * exchange. */ + register_socket_transport(fd, "host", port, 1); + adb_write(fd, _start_req, strlen(_start_req)); + } + + /* Prepare for accepting of the next ADB host connection. */ + fd = qemu_pipe_open(con_name); + if (fd < 0) { + D("adb service become unavailable.\n"); + return 0; + } + } else { + D("Unable to send the '%s' request to ADB service.\n", _accept_req); + return 0; + } + } + D("transport: qemu_socket_thread() exiting\n"); + return 0; +} +#endif // !ADB_HOST + +void local_init(int port) +{ + adb_thread_t thr; + void* (*func)(void *); + + if(HOST) { + func = client_socket_thread; + } else { +#if ADB_HOST + func = server_socket_thread; +#else + /* For the adbd daemon in the system image we need to distinguish + * between the device, and the emulator. */ + char is_qemu[PROPERTY_VALUE_MAX]; + property_get("ro.kernel.qemu", is_qemu, ""); + if (!strcmp(is_qemu, "1")) { + /* Running inside the emulator: use QEMUD pipe as the transport. */ + func = qemu_socket_thread; + } else { + /* Running inside the device: use TCP socket as the transport. */ + func = server_socket_thread; + } +#endif // !ADB_HOST + } + + D("transport: local %s init\n", HOST ? "client" : "server"); + + if(adb_thread_create(&thr, func, (void *) (uintptr_t) port)) { + fatal_errno("cannot create local socket %s thread", + HOST ? "client" : "server"); + } +} + +static void remote_kick(atransport *t) +{ + int fd = t->sfd; + t->sfd = -1; + adb_shutdown(fd); + adb_close(fd); + +#if ADB_HOST + if(HOST) { + int nn; + adb_mutex_lock( &local_transports_lock ); + for (nn = 0; nn < ADB_LOCAL_TRANSPORT_MAX; nn++) { + if (local_transports[nn] == t) { + local_transports[nn] = NULL; + break; + } + } + adb_mutex_unlock( &local_transports_lock ); + } +#endif +} + +static void remote_close(atransport *t) +{ + adb_close(t->fd); +} + + +#if ADB_HOST +/* Only call this function if you already hold local_transports_lock. */ +atransport* find_emulator_transport_by_adb_port_locked(int adb_port) +{ + int i; + for (i = 0; i < ADB_LOCAL_TRANSPORT_MAX; i++) { + if (local_transports[i] && local_transports[i]->adb_port == adb_port) { + return local_transports[i]; + } + } + return NULL; +} + +atransport* find_emulator_transport_by_adb_port(int adb_port) +{ + adb_mutex_lock( &local_transports_lock ); + atransport* result = find_emulator_transport_by_adb_port_locked(adb_port); + adb_mutex_unlock( &local_transports_lock ); + return result; +} + +/* Only call this function if you already hold local_transports_lock. */ +int get_available_local_transport_index_locked() +{ + int i; + for (i = 0; i < ADB_LOCAL_TRANSPORT_MAX; i++) { + if (local_transports[i] == NULL) { + return i; + } + } + return -1; +} + +int get_available_local_transport_index() +{ + adb_mutex_lock( &local_transports_lock ); + int result = get_available_local_transport_index_locked(); + adb_mutex_unlock( &local_transports_lock ); + return result; +} +#endif + +int init_socket_transport(atransport *t, int s, int adb_port, int local) +{ + int fail = 0; + + t->kick = remote_kick; + t->close = remote_close; + t->read_from_remote = remote_read; + t->write_to_remote = remote_write; + t->sfd = s; + t->sync_token = 1; + t->connection_state = CS_OFFLINE; + t->type = kTransportLocal; + t->adb_port = 0; + +#if ADB_HOST + if (HOST && local) { + adb_mutex_lock( &local_transports_lock ); + { + t->adb_port = adb_port; + atransport* existing_transport = + find_emulator_transport_by_adb_port_locked(adb_port); + int index = get_available_local_transport_index_locked(); + if (existing_transport != NULL) { + D("local transport for port %d already registered (%p)?\n", + adb_port, existing_transport); + fail = -1; + } else if (index < 0) { + // Too many emulators. + D("cannot register more emulators. Maximum is %d\n", + ADB_LOCAL_TRANSPORT_MAX); + fail = -1; + } else { + local_transports[index] = t; + } + } + adb_mutex_unlock( &local_transports_lock ); + } +#endif + return fail; +} diff --git a/minuitwrp/Android.mk b/minuitwrp/Android.mk index 2ca2091e1a..c844082833 100644 --- a/minuitwrp/Android.mk +++ b/minuitwrp/Android.mk @@ -10,6 +10,13 @@ LOCAL_SRC_FILES := \ graphics_utils.cpp \ events.cpp +ifeq ($(TW_SUPPORT_INPUT_1_2_HAPTICS),true) + ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 28; echo $$?),0) + LOCAL_SHARED_LIBRARIES += android.hardware.vibrator@1.2 libhidlbase + LOCAL_CFLAGS += -DUSE_QTI_HAPTICS + endif +endif + ifneq ($(TW_BOARD_CUSTOM_GRAPHICS),) $(warning ****************************************************************************) $(warning * TW_BOARD_CUSTOM_GRAPHICS support has been deprecated in TWRP. *) @@ -142,9 +149,6 @@ ifneq ($(TARGET_RECOVERY_OVERSCAN_PERCENT),) else LOCAL_CFLAGS += -DOVERSCAN_PERCENT=0 endif -ifeq ($(TW_SCREEN_BLANK_ON_BOOT), true) - LOCAL_CFLAGS += -DTW_SCREEN_BLANK_ON_BOOT -endif ifeq ($(TW_FBIOPAN), true) LOCAL_CFLAGS += -DTW_FBIOPAN endif @@ -183,6 +187,11 @@ ifneq ($(TW_WHITELIST_INPUT),) LOCAL_CFLAGS += -DWHITELIST_INPUT=$(TW_WHITELIST_INPUT) endif +ifeq ($(TW_HAPTICS_TSPDRV), true) + LOCAL_SRC_FILES += tspdrv.cpp + LOCAL_CFLAGS += -DTW_HAPTICS_TSPDRV +endif + ifeq ($(TW_DISABLE_TTF), true) $(warning ****************************************************************************) $(warning * TW_DISABLE_TTF support has been deprecated in TWRP. *) diff --git a/minuitwrp/events.cpp b/minuitwrp/events.cpp index a2a3d166b3..cfe2948bb0 100755 --- a/minuitwrp/events.cpp +++ b/minuitwrp/events.cpp @@ -28,6 +28,10 @@ #include #include +#ifdef USE_QTI_HAPTICS +#include +#endif + #include "../common.h" #include "minui.h" @@ -104,7 +108,7 @@ static struct pollfd ev_fds[MAX_DEVICES]; static struct ev evs[MAX_DEVICES]; static unsigned ev_count = 0; static struct timeval lastInputStat; -static time_t lastInputMTime; +struct timespec lastInputMTim; static int has_mouse = 0; static inline int ABS(int x) { @@ -124,21 +128,29 @@ int write_to_file(const std::string& fn, const std::string& line) { } #ifndef TW_NO_HAPTICS +#ifndef TW_HAPTICS_TSPDRV int vibrate(int timeout_ms) { if (timeout_ms > 10000) timeout_ms = 1000; char tout[6]; sprintf(tout, "%i", timeout_ms); +#ifdef USE_QTI_HAPTICS + android::sp vib = android::hardware::vibrator::V1_2::IVibrator::getService(); + if (vib != nullptr) { + vib->on((uint32_t)timeout_ms); + } +#else if (std::ifstream(LEDS_HAPTICS_ACTIVATE_FILE).good()) { write_to_file(LEDS_HAPTICS_DURATION_FILE, tout); write_to_file(LEDS_HAPTICS_ACTIVATE_FILE, "1"); } else write_to_file(VIBRATOR_TIMEOUT_FILE, tout); - +#endif return 0; } #endif +#endif /* Returns empty tokens */ static char *vk_strtok_r(char *str, const char *delim, char **save_str) @@ -351,8 +363,12 @@ int ev_init(void) } struct stat st; - if(stat("/dev/input", &st) >= 0) - lastInputMTime = st.st_mtime; + if(stat("/dev/input", &st) >= 0) { + lastInputMTim = st.st_mtim; +#ifdef _EVENT_LOGGING + printf("ev_init: lastInputMTim sec: %lu, nsec: %lu\n", st.st_mtim.tv_sec, st.st_mtim.tv_nsec); +#endif + } gettimeofday(&lastInputStat, NULL); return 0; @@ -766,12 +782,13 @@ int ev_get(struct input_event *ev, int timeout_ms) { struct stat st; stat("/dev/input", &st); - if (st.st_mtime > lastInputMTime) + if ((st.st_mtim.tv_sec > lastInputMTim.tv_sec) + || (st.st_mtim.tv_sec == lastInputMTim.tv_sec && st.st_mtim.tv_nsec > lastInputMTim.tv_nsec)) { LOGI("Reloading input devices\n"); ev_exit(); ev_init(); - lastInputMTime = st.st_mtime; + lastInputMTim = st.st_mtim; } lastInputStat = curr; } diff --git a/minuitwrp/graphics.cpp b/minuitwrp/graphics.cpp index 47ff3b9179..b387b703bf 100644 --- a/minuitwrp/graphics.cpp +++ b/minuitwrp/graphics.cpp @@ -31,6 +31,7 @@ #include +#include #include #include "../gui/placement.h" #include "minui.h" @@ -60,6 +61,8 @@ static GGLContext *gr_context = 0; GGLSurface gr_mem_surface; static int gr_is_curr_clr_opaque = 0; +unsigned int gr_rotation = 0; + int gr_textEx_scaleW(int x, int y, const char *s, void* pFont, int max_width, int placement, int scale) { GGLContext *gl = gr_context; @@ -114,17 +117,20 @@ void gr_clip(int x, int y, int w, int h) { GGLContext *gl = gr_context; -#if TW_ROTATION == 0 - gl->scissor(gl, x, y, w, h); -#elif TW_ROTATION == 90 - gl->scissor(gl, gr_draw->width - y - h, x, h, w); -#elif TW_ROTATION == 270 - gl->scissor(gl, y, gr_draw->height - x - w, h, w); -#else - int t_disp = gr_draw->height - y - h; - int l_disp = gr_draw->width - x - w; - gl->scissor(gl, l_disp, t_disp, w, h); -#endif + switch (gr_rotation) { + case 90: + gl->scissor(gl, gr_draw->width - y - h, x, h, w); + break; + case 180: + gl->scissor(gl, gr_draw->width - x - w, gr_draw->height - y - h, w, h); + break; + case 270: + gl->scissor(gl, y, gr_draw->height - x - w, h, w); + break; + default: + gl->scissor(gl, x, y, w, h); + break; + } gl->enable(gl, GGL_SCISSOR_TEST); } @@ -142,10 +148,10 @@ void gr_line(int x0, int y0, int x1, int y1, int width) GGLContext *gl = gr_context; int x0_disp, y0_disp, x1_disp, y1_disp; - x0_disp = ROTATION_X_DISP(x0, y0, gr_draw); - y0_disp = ROTATION_Y_DISP(x0, y0, gr_draw); - x1_disp = ROTATION_X_DISP(x1, y1, gr_draw); - y1_disp = ROTATION_Y_DISP(x1, y1, gr_draw); + x0_disp = ROTATION_X_DISP(x0, y0, gr_draw->width); + y0_disp = ROTATION_Y_DISP(x0, y0, gr_draw->height); + x1_disp = ROTATION_X_DISP(x1, y1, gr_draw->width); + y1_disp = ROTATION_Y_DISP(x1, y1, gr_draw->height); if(gr_is_curr_clr_opaque) gl->disable(gl, GGL_BLEND); @@ -245,10 +251,10 @@ void gr_fill(int x, int y, int w, int h) if(gr_is_curr_clr_opaque) gl->disable(gl, GGL_BLEND); - x0_disp = ROTATION_X_DISP(x, y, gr_draw); - y0_disp = ROTATION_Y_DISP(x, y, gr_draw); - x1_disp = ROTATION_X_DISP(x + w, y + h, gr_draw); - y1_disp = ROTATION_Y_DISP(x + w, y + h, gr_draw); + x0_disp = ROTATION_X_DISP(x, y, gr_draw->width); + y0_disp = ROTATION_Y_DISP(x, y, gr_draw->height); + x1_disp = ROTATION_X_DISP(x + w, y + h, gr_draw->width); + y1_disp = ROTATION_Y_DISP(x + w, y + h, gr_draw->height); l_disp = std::min(x0_disp, x1_disp); r_disp = std::max(x0_disp, x1_disp); t_disp = std::min(y0_disp, y1_disp); @@ -275,35 +281,36 @@ void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy) int dx0_disp, dy0_disp, dx1_disp, dy1_disp; int l_disp, r_disp, t_disp, b_disp; - // Figuring out display coordinates works for TW_ROTATION == 0 too, + // Figuring out display coordinates works for gr_rotation == 0 too, // and isn't as expensive as allocating and rotating another surface, // so we do this anyway. - dx0_disp = ROTATION_X_DISP(dx, dy, gr_draw); - dy0_disp = ROTATION_Y_DISP(dx, dy, gr_draw); - dx1_disp = ROTATION_X_DISP(dx + w, dy + h, gr_draw); - dy1_disp = ROTATION_Y_DISP(dx + w, dy + h, gr_draw); + dx0_disp = ROTATION_X_DISP(dx, dy, gr_draw->width); + dy0_disp = ROTATION_Y_DISP(dx, dy, gr_draw->height); + dx1_disp = ROTATION_X_DISP(dx + w, dy + h, gr_draw->width); + dy1_disp = ROTATION_Y_DISP(dx + w, dy + h, gr_draw->height); l_disp = std::min(dx0_disp, dx1_disp); r_disp = std::max(dx0_disp, dx1_disp); t_disp = std::min(dy0_disp, dy1_disp); b_disp = std::max(dy0_disp, dy1_disp); -#if TW_ROTATION != 0 - // Do not perform relatively expensive operation if not needed GGLSurface surface_rotated; - surface_rotated.version = sizeof(surface_rotated); - // Skip the **(TW_ROTATION == 0)** || (TW_ROTATION == 180) check - // because we are under a TW_ROTATION != 0 conditional compilation statement - surface_rotated.width = (TW_ROTATION == 180) ? surface->width : surface->height; - surface_rotated.height = (TW_ROTATION == 180) ? surface->height : surface->width; - surface_rotated.stride = surface_rotated.width; - surface_rotated.format = surface->format; - surface_rotated.data = (GGLubyte*) malloc(surface_rotated.stride * surface_rotated.height * 4); - surface_ROTATION_transform((gr_surface) &surface_rotated, (const gr_surface) surface, 4); - - gl->bindTexture(gl, &surface_rotated); -#else - gl->bindTexture(gl, surface); -#endif + if (gr_rotation != 0) { + // Do not perform relatively expensive operation if not needed + surface_rotated.version = sizeof(surface_rotated); + // Skip the **(gr_rotation == 0)** || (gr_rotation == 180) check + // because we are under a gr_rotation != 0 conditional compilation statement + surface_rotated.width = (gr_rotation == 180) ? surface->width : surface->height; + surface_rotated.height = (gr_rotation == 180) ? surface->height : surface->width; + surface_rotated.stride = surface_rotated.width; + surface_rotated.format = surface->format; + surface_rotated.data = (GGLubyte*) malloc(surface_rotated.stride * surface_rotated.height * 4); + surface_ROTATION_transform((gr_surface) &surface_rotated, (const gr_surface) surface, 4); + + gl->bindTexture(gl, &surface_rotated); + } else { + gl->bindTexture(gl, surface); + } + gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE); gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); @@ -312,9 +319,8 @@ void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy) gl->recti(gl, l_disp, t_disp, r_disp, b_disp); gl->disable(gl, GGL_TEXTURE_2D); -#if TW_ROTATION != 0 - free(surface_rotated.data); -#endif + if (gr_rotation != 0) + free(surface_rotated.data); if(surface->format == GGL_PIXEL_FORMAT_RGBX_8888) gl->enable(gl, GGL_BLEND); @@ -355,6 +361,14 @@ int gr_init(void) { gr_draw = NULL; + char gr_rotation_string[PROPERTY_VALUE_MAX]; + char default_rotation[4]; + snprintf(default_rotation, 4, "%d", TW_ROTATION); + property_get("persist.twrp.rotation", gr_rotation_string, default_rotation); + gr_rotation = atoi(gr_rotation_string); + if (!(gr_rotation == 90 || gr_rotation == 180 || gr_rotation == 270)) + gr_rotation = 0; + #ifdef MSM_BSP gr_backend = open_overlay(); if (gr_backend) { @@ -421,12 +435,6 @@ int gr_init(void) gr_flip(); gr_flip(); -#ifdef TW_SCREEN_BLANK_ON_BOOT - printf("TW_SCREEN_BLANK_ON_BOOT := true\n"); - gr_fb_blank(true); - gr_fb_blank(false); -#endif - return 0; } @@ -437,14 +445,14 @@ void gr_exit(void) int gr_fb_width(void) { - return (TW_ROTATION == 0 || TW_ROTATION == 180) ? + return (gr_rotation == 0 || gr_rotation == 180) ? gr_draw->width - 2 * overscan_offset_x : gr_draw->height - 2 * overscan_offset_y; } int gr_fb_height(void) { - return (TW_ROTATION == 0 || TW_ROTATION == 180) ? + return (gr_rotation == 0 || gr_rotation == 180) ? gr_draw->height - 2 * overscan_offset_y : gr_draw->width - 2 * overscan_offset_x; } diff --git a/minuitwrp/graphics_overlay.cpp b/minuitwrp/graphics_overlay.cpp index 4dff7f4a69..a53faa865e 100644 --- a/minuitwrp/graphics_overlay.cpp +++ b/minuitwrp/graphics_overlay.cpp @@ -324,7 +324,7 @@ int allocate_overlay(int fd, GRSurface gr_fb) overlayL.dst_rect.h = gr_fb.height; overlayL.alpha = 0xFF; // If this worked, life would have been so much easier - //switch (TW_ROTATION) { + //switch (gr_rotation) { //case 0: overlayL.flags = MDP_ROT_NOP; break; //case 90: overlayL.flags = MDP_ROT_90; break; //case 180: overlayL.flags = MDP_ROT_180; break; @@ -368,7 +368,7 @@ int allocate_overlay(int fd, GRSurface gr_fb) overlayL.dst_rect.h = height; overlayL.alpha = 0xFF; // If this worked, life would have been so much easier - //switch (TW_ROTATION) { + //switch (gr_rotation) { //case 0: overlayL.flags = MDP_ROT_NOP; break; //case 90: overlayL.flags = MDP_ROT_90; break; //case 180: overlayL.flags = MDP_ROT_180; break; @@ -403,7 +403,7 @@ int allocate_overlay(int fd, GRSurface gr_fb) overlayR.alpha = 0xFF; overlayR.flags = MDSS_MDP_RIGHT_MIXER; // If this worked, life would have been so much easier - //switch (TW_ROTATION) { + //switch (gr_rotation) { //case 0: overlayR.flags |= MDP_ROT_NOP; break; //case 90: overlayR.flags |= MDP_ROT_90; break; //case 180: overlayR.flags |= MDP_ROT_180; break; diff --git a/minuitwrp/graphics_utils.cpp b/minuitwrp/graphics_utils.cpp index c591e5398f..0bc86828d1 100644 --- a/minuitwrp/graphics_utils.cpp +++ b/minuitwrp/graphics_utils.cpp @@ -26,6 +26,7 @@ struct fb_var_screeninfo vi; extern GGLSurface gr_mem_surface; extern GRSurface* gr_draw; +extern unsigned int gr_rotation; int gr_save_screenshot(const char *dest) { @@ -123,6 +124,20 @@ int gr_save_screenshot(const char *dest) return res; } +int ROTATION_X_DISP(int x, int y, int w) { + return ((gr_rotation == 0) ? (x) : + (gr_rotation == 90) ? (w - (y) - 1) : + (gr_rotation == 180) ? (w - (x) - 1) : + (gr_rotation == 270) ? (y) : -1); +} + +int ROTATION_Y_DISP(int x, int y, int h) { + return ((gr_rotation == 0) ? (y) : + (gr_rotation == 90) ? (x) : + (gr_rotation == 180) ? (h - (y) - 1) : + (gr_rotation == 270) ? (h - (x) - 1) : -1); +} + #define MATRIX_ELEMENT(matrix, row, col, row_size, elem_size) \ (((uint8_t*) (matrix)) + (((row) * (elem_size)) * (row_size)) + ((col) * (elem_size))) @@ -135,8 +150,8 @@ int gr_save_screenshot(const char *dest) /* input pointer from src->data */ \ const uint##bits_per_pixel##_t *ip; \ /* Display coordinates (in dst) corresponding to (x, y) in src */ \ - size_t x_disp = ROTATION_X_DISP(x, y, dst); \ - size_t y_disp = ROTATION_Y_DISP(x, y, dst); \ + size_t x_disp = ROTATION_X_DISP(x, y, dst->width); \ + size_t y_disp = ROTATION_Y_DISP(x, y, dst->height); \ \ ip = (const uint##bits_per_pixel##_t*) \ MATRIX_ELEMENT(src->data, y, x, \ diff --git a/minuitwrp/minui.h b/minuitwrp/minui.h index 2c462e75f7..a6c2a712ce 100644 --- a/minuitwrp/minui.h +++ b/minuitwrp/minui.h @@ -76,16 +76,9 @@ int gr_save_screenshot(const char *dest); // Transform minuitwrp API coordinates into display coordinates, // for panels that are hardware-mounted in a rotated manner. -#define ROTATION_X_DISP(x, y, surface) \ - ((TW_ROTATION == 0) ? (x) : \ - (TW_ROTATION == 90) ? ((surface)->width - (y) - 1) : \ - (TW_ROTATION == 180) ? ((surface)->width - (x) - 1) : \ - (TW_ROTATION == 270) ? (y) : -1) -#define ROTATION_Y_DISP(x, y, surface) \ - ((TW_ROTATION == 0) ? (y) : \ - (TW_ROTATION == 90) ? (x) : \ - (TW_ROTATION == 180) ? ((surface)->height - (y) - 1) : \ - (TW_ROTATION == 270) ? ((surface)->height - (x) - 1) : -1) +int ROTATION_X_DISP(int x, int y, int w); + +int ROTATION_Y_DISP(int x, int y, int h); void surface_ROTATION_transform(gr_surface dst_ptr, const gr_surface src_ptr, size_t num_bytes_per_pixel); diff --git a/minuitwrp/truetype.cpp b/minuitwrp/truetype.cpp index 0416b0e9f7..9c7c79b07c 100644 --- a/minuitwrp/truetype.cpp +++ b/minuitwrp/truetype.cpp @@ -20,6 +20,8 @@ #define STRING_CACHE_MAX_ENTRIES 400 #define STRING_CACHE_TRUNCATE_ENTRIES 150 +extern unsigned int gr_rotation; + typedef struct { int size; @@ -725,20 +727,20 @@ int gr_ttf_textExWH(void *context, int x, int y, return -1; } -#if TW_ROTATION != 0 - // Do not perform relatively expensive operation if not needed GGLSurface string_surface_rotated; - string_surface_rotated.version = sizeof(string_surface_rotated); - // Skip the **(TW_ROTATION == 0)** || (TW_ROTATION == 180) check - // because we are under a TW_ROTATION != 0 conditional compilation statement - string_surface_rotated.width = (TW_ROTATION == 180) ? e->surface.width : e->surface.height; - string_surface_rotated.height = (TW_ROTATION == 180) ? e->surface.height : e->surface.width; - string_surface_rotated.stride = string_surface_rotated.width; - string_surface_rotated.format = e->surface.format; - // e->surface.format is GGL_PIXEL_FORMAT_A_8 (grayscale) - string_surface_rotated.data = (GGLubyte*) malloc(string_surface_rotated.stride * string_surface_rotated.height * 1); - surface_ROTATION_transform((gr_surface) &string_surface_rotated, (const gr_surface) &e->surface, 1); -#endif + if (gr_rotation != 0) { + // Do not perform relatively expensive operation if not needed + string_surface_rotated.version = sizeof(string_surface_rotated); + // Skip the **(gr_rotation == 0)** || (gr_rotation == 180) check + // because we are under a gr_rotation != 0 conditional compilation statement + string_surface_rotated.width = (gr_rotation == 180) ? e->surface.width : e->surface.height; + string_surface_rotated.height = (gr_rotation == 180) ? e->surface.height : e->surface.width; + string_surface_rotated.stride = string_surface_rotated.width; + string_surface_rotated.format = e->surface.format; + // e->surface.format is GGL_PIXEL_FORMAT_A_8 (grayscale) + string_surface_rotated.data = (GGLubyte*) malloc(string_surface_rotated.stride * string_surface_rotated.height * 1); + surface_ROTATION_transform((gr_surface) &string_surface_rotated, (const gr_surface) &e->surface, 1); + } int y_bottom = y + e->surface.height; int res = e->rendered_bytes; @@ -753,26 +755,26 @@ int gr_ttf_textExWH(void *context, int x, int y, } } - // Figuring out display coordinates works for TW_ROTATION == 0 too, + // Figuring out display coordinates works for gr_rotation == 0 too, // and isn't as expensive as allocating and rotating another surface, // so we do this anyway. int x0_disp, y0_disp, x1_disp, y1_disp; int l_disp, r_disp, t_disp, b_disp; - x0_disp = ROTATION_X_DISP(x, y, gr_draw); - y0_disp = ROTATION_Y_DISP(x, y, gr_draw); - x1_disp = ROTATION_X_DISP(x + e->surface.width, y_bottom, gr_draw); - y1_disp = ROTATION_Y_DISP(x + e->surface.width, y_bottom, gr_draw); + x0_disp = ROTATION_X_DISP(x, y, gr_draw->width); + y0_disp = ROTATION_Y_DISP(x, y, gr_draw->height); + x1_disp = ROTATION_X_DISP(x + e->surface.width, y_bottom, gr_draw->width); + y1_disp = ROTATION_Y_DISP(x + e->surface.width, y_bottom, gr_draw->height); l_disp = std::min(x0_disp, x1_disp); r_disp = std::max(x0_disp, x1_disp); t_disp = std::min(y0_disp, y1_disp); b_disp = std::max(y0_disp, y1_disp); -#if TW_ROTATION != 0 - gl->bindTexture(gl, &string_surface_rotated); -#else - gl->bindTexture(gl, &e->surface); -#endif + if (gr_rotation != 0) { + gl->bindTexture(gl, &string_surface_rotated); + } else { + gl->bindTexture(gl, &e->surface); + } gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE); gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); @@ -782,9 +784,8 @@ int gr_ttf_textExWH(void *context, int x, int y, gl->recti(gl, l_disp, t_disp, r_disp, b_disp); gl->disable(gl, GGL_TEXTURE_2D); -#if TW_ROTATION != 0 - free(string_surface_rotated.data); -#endif + if (gr_rotation != 0) + free(string_surface_rotated.data); pthread_mutex_unlock(&font->mutex); return res; diff --git a/minuitwrp/tspdrv.cpp b/minuitwrp/tspdrv.cpp new file mode 100644 index 0000000000..6967cd59b7 --- /dev/null +++ b/minuitwrp/tspdrv.cpp @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "tspdrv.h" + +int tspdrv_initialized = 0; +int tspdrv_file_desc; +int tspdrv_numActuators = 0; + +int initialize_tspdrv() +{ + // Open device file as read/write for ioctl and write + tspdrv_file_desc = open(TSPDRV, O_RDWR); + if(tspdrv_file_desc < 0) + { + printf("Failed to open device file: %s", TSPDRV); + return -1; + } + + // create default device parameters + device_parameter dev_param1 { 0, VIBE_KP_CFG_FREQUENCY_PARAM1, 0}; + device_parameter dev_param2 { 0, VIBE_KP_CFG_FREQUENCY_PARAM2, 0}; + device_parameter dev_param3 { 0, VIBE_KP_CFG_FREQUENCY_PARAM3, 0}; + device_parameter dev_param4 { 0, VIBE_KP_CFG_FREQUENCY_PARAM4, 400}; + device_parameter dev_param5 { 0, VIBE_KP_CFG_FREQUENCY_PARAM5, 13435}; + device_parameter dev_param6 { 0, VIBE_KP_CFG_FREQUENCY_PARAM6, 0}; + device_parameter dev_param_update_rate {0, VIBE_KP_CFG_UPDATE_RATE_MS, 5}; + + // Set magic number for vibration driver, wont allow us to write data without! + int ret = ioctl(tspdrv_file_desc, TSPDRV_SET_MAGIC_NUMBER, TSPDRV_MAGIC_NUMBER); + if(ret != 0) + { + printf("Failed to set magic number"); + return -ret; + } + + // Set default device parameter 1 + ret = ioctl(tspdrv_file_desc, TSPDRV_SET_DEVICE_PARAMETER, &dev_param1); + if(ret != 0) + { + printf("Failed to set device parameter 1"); + return -ret; + } + + // Set default device parameter 2 + ret = ioctl(tspdrv_file_desc, TSPDRV_SET_DEVICE_PARAMETER, &dev_param2); + if(ret != 0) + { + printf("Failed to set device parameter 2"); + return -ret; + } + + // Set default device parameter 3 + ret = ioctl(tspdrv_file_desc, TSPDRV_SET_DEVICE_PARAMETER, &dev_param3); + if(ret != 0) + { + printf("Failed to set device parameter 3"); + return -ret; + } + + // Set default device parameter 4 + ret = ioctl(tspdrv_file_desc, TSPDRV_SET_DEVICE_PARAMETER, &dev_param4); + if(ret != 0) + { + printf("Failed to set device parameter 4"); + return -ret; + } + + // Set default device parameter 5 + ret = ioctl(tspdrv_file_desc, TSPDRV_SET_DEVICE_PARAMETER, &dev_param5); + if(ret != 0) + { + printf("Failed to set device parameter 5"); + return -ret; + } + + // Set default device parameter 6 + ret = ioctl(tspdrv_file_desc, TSPDRV_SET_DEVICE_PARAMETER, &dev_param6); + if(ret != 0) + { + printf("Failed to set device parameter 6"); + return -ret; + } + + // Set default device parameter update rate + ret = ioctl(tspdrv_file_desc, TSPDRV_SET_DEVICE_PARAMETER, &dev_param_update_rate); + if(ret != 0) + { + printf("Failed to set device parameter update rate"); + return -ret; + } + + // Get number of actuators the device has + ret = ioctl(tspdrv_file_desc, TSPDRV_GET_NUM_ACTUATORS, 0); + if(ret == 0) + { + printf("No actuators found!"); + return -2; + } + + tspdrv_numActuators = ret; + tspdrv_initialized = 1; + return 0; +} + +int tspdrv_off() { + + for(int32_t i = 0; i < tspdrv_numActuators; i++) + { + int32_t ret = ioctl(tspdrv_file_desc, TSPDRV_DISABLE_AMP, i); + if(ret != 0) + { + printf("Failed to deactivate Actuator with index %d", i); + return -1; + } + } + + return 0; +} + +int vibrate(int timeout_ms) +{ + double BUFFER_ENTRIES_PER_MS = 8.21; + uint8_t DEFAULT_AMPLITUDE = 127; + int32_t OUTPUT_BUFFER_SIZE = 40; + + if(!tspdrv_initialized) + { + printf("Initializing TSPDRV\n"); + if(initialize_tspdrv() == 0) + { + printf("TSPDRV initialized\n"); + } + } + + // Calculate needed buffer entries + int32_t bufferSize = (int32_t) round(BUFFER_ENTRIES_PER_MS * timeout_ms); + VibeUInt8 fullBuffer[bufferSize]; + + // turn previous vibrations off + tspdrv_off(); + + for(int32_t i = 0; i < bufferSize; i++) + { + // The vibration is a sine curve, the negative parts are 255 + negative value + fullBuffer[i] = (VibeUInt8) (DEFAULT_AMPLITUDE * sin(i/BUFFER_ENTRIES_PER_MS)); + } + + // Amount of buffer arrays with size of OUTPUT_BUFFER_SIZE + int32_t numBuffers = (int32_t) ceil((double)bufferSize / (double)OUTPUT_BUFFER_SIZE); + VibeUInt8 outputBuffers[numBuffers][OUTPUT_BUFFER_SIZE]; + memset(outputBuffers, 0, sizeof(outputBuffers)); // zero the array before we fill it with values + + for(int32_t i = 0; i < bufferSize; i++) + { + // split fullBuffer into multiple smaller buffers with size OUTPUT_BUFFER_SIZE + outputBuffers[i/OUTPUT_BUFFER_SIZE][i%OUTPUT_BUFFER_SIZE] = fullBuffer[i]; + } + + for(int32_t i = 0; i < tspdrv_numActuators; i++) + { + for(int32_t j = 0; j < numBuffers; j++) + { + char output[OUTPUT_BUFFER_SIZE + SPI_HEADER_SIZE]; + memset(output, 0, sizeof(output)); + output[0] = i; // first byte is actuator index + output[1] = 8; // per definition has to be 8 + output[2] = OUTPUT_BUFFER_SIZE; // size of the following output buffer + for(int32_t k = 3; k < OUTPUT_BUFFER_SIZE+3; k++) + { + output[k] = outputBuffers[j][k-3]; + } + // write the buffer to the device + write(tspdrv_file_desc, output, sizeof(output)); + if((j+1) % 4 == 0) + { + // every 4 buffers, but not the first if theres only 1, we send an ENABLE_AMP signal + int32_t ret = ioctl(tspdrv_file_desc, TSPDRV_ENABLE_AMP, i); + if(ret != 0) + { + printf("Failed to activate Actuator with index %d", i); + return -1; + } + } + } + } + return 0; +} \ No newline at end of file diff --git a/minuitwrp/tspdrv.h b/minuitwrp/tspdrv.h new file mode 100644 index 0000000000..afb294eeaf --- /dev/null +++ b/minuitwrp/tspdrv.h @@ -0,0 +1,100 @@ +/* +** ========================================================================= +** File: +** tspdrv.h +** +** Description: +** Constants and type definitions for the TouchSense Kernel Module. +** +** Portions Copyright (c) 2008-2017 Immersion Corporation. All Rights Reserved. +** +** This file contains Original Code and/or Modifications of Original Code +** as defined in and that are subject to the GNU Public License v2 - +** (the 'License'). You may not use this file except in compliance with the +** License. You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, Inc., +** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or contact +** TouchSenseSales@immersion.com. +** +** The Original Code and all software distributed under the License are +** distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +** EXPRESS OR IMPLIED, AND IMMERSION HEREBY DISCLAIMS ALL SUCH WARRANTIES, +** INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS +** FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see +** the License for the specific language governing rights and limitations +** under the License. +** ========================================================================= +*/ + +#ifndef _TSPDRV_H +#define _TSPDRV_H + +/* Constants */ +#define MODULE_NAME "tspdrv" +#define TSPDRV "/dev/tspdrv" +#define TSPDRV_MAGIC_NUMBER 0x494D4D52 +#define TSPDRV_IOCTL_GROUP 0x52 +#define TSPDRV_STOP_KERNEL_TIMER _IO(TSPDRV_IOCTL_GROUP, 1) /* obsolete, may be removed in future */ +#define TSPDRV_SET_MAGIC_NUMBER _IO(TSPDRV_IOCTL_GROUP, 2) +#define TSPDRV_ENABLE_AMP _IO(TSPDRV_IOCTL_GROUP, 3) +#define TSPDRV_DISABLE_AMP _IO(TSPDRV_IOCTL_GROUP, 4) +#define TSPDRV_GET_NUM_ACTUATORS _IO(TSPDRV_IOCTL_GROUP, 5) +#define TSPDRV_SET_DEVICE_PARAMETER _IO(TSPDRV_IOCTL_GROUP, 6) +#define TSPDRV_SET_DBG_LEVEL _IO(TSPDRV_IOCTL_GROUP, 7) +#define TSPDRV_GET_DBG_LEVEL _IO(TSPDRV_IOCTL_GROUP, 8) +#define TSPDRV_SET_RUNTIME_RECORD_FLAG _IO(TSPDRV_IOCTL_GROUP, 9) +#define TSPDRV_GET_RUNTIME_RECORD_FLAG _IO(TSPDRV_IOCTL_GROUP, 10) +#define TSPDRV_SET_RUNTIME_RECORD_BUF_SIZE _IO(TSPDRV_IOCTL_GROUP, 11) +#define TSPDRV_GET_RUNTIME_RECORD_BUF_SIZE _IO(TSPDRV_IOCTL_GROUP, 12) +#define TSPDRV_GET_PARAM_FILE_ID _IO(TSPDRV_IOCTL_GROUP, 13) +#define TSPDRV_GET_DEVICE_STATUS _IO(TSPDRV_IOCTL_GROUP, 14) +/* +** Frequency constant parameters to control force output values and signals. +*/ +#define VIBE_KP_CFG_FREQUENCY_PARAM1 85 +#define VIBE_KP_CFG_FREQUENCY_PARAM2 86 +#define VIBE_KP_CFG_FREQUENCY_PARAM3 87 +#define VIBE_KP_CFG_FREQUENCY_PARAM4 88 +#define VIBE_KP_CFG_FREQUENCY_PARAM5 89 +#define VIBE_KP_CFG_FREQUENCY_PARAM6 90 + +/* +** Force update rate in milliseconds. +*/ +#define VIBE_KP_CFG_UPDATE_RATE_MS 95 + +#define VIBE_MAX_DEVICE_NAME_LENGTH 64 +#define SPI_HEADER_SIZE 3 /* DO NOT CHANGE - SPI buffer header size */ +#define VIBE_OUTPUT_SAMPLE_SIZE 50 /* DO NOT CHANGE - maximum number of samples */ +#define MAX_DEBUG_BUFFER_LENGTH 1024 + +typedef int8_t VibeInt8; +typedef u_int8_t VibeUInt8; +typedef int16_t VibeInt16; +typedef u_int16_t VibeUInt16; +typedef int32_t VibeInt32; +typedef u_int32_t VibeUInt32; +typedef u_int8_t VibeBool; +typedef VibeInt32 VibeStatus; + +/* Device parameters sent to the kernel module, tspdrv.ko */ +typedef struct +{ + VibeInt32 nDeviceIndex; + VibeInt32 nDeviceParamID; + VibeInt32 nDeviceParamValue; +} device_parameter; + +typedef struct +{ + VibeUInt8 nActuatorIndex; /* 1st byte is actuator index */ + VibeUInt8 nBitDepth; /* 2nd byte is bit depth */ + VibeUInt8 nBufferSize; /* 3rd byte is data size */ + VibeUInt8 dataBuffer[40]; +} actuator_samples_buffer; + +/* Error and Return value codes */ +#define VIBE_S_SUCCESS 0 /* Success */ +#define VIBE_E_FAIL -4 /* Generic error */ + +#endif /* _TSPDRV_H */ diff --git a/openrecoveryscript.cpp b/openrecoveryscript.cpp index 165211523c..00b25f1a5c 100755 --- a/openrecoveryscript.cpp +++ b/openrecoveryscript.cpp @@ -62,10 +62,16 @@ OpenRecoveryScript::VoidFunction OpenRecoveryScript::call_after_cli_command; #define SCRIPT_COMMAND_SIZE 512 int OpenRecoveryScript::check_for_script_file(void) { - std::string orsFile = TWFunc::get_cache_dir() + "/recovery/openrecoveryscript"; + std::string logDir = TWFunc::get_log_dir(); + std::string orsFile; + if (logDir == DATA_LOGS_DIR) + orsFile = "/data/cache"; + else + orsFile = logDir; + orsFile += "/recovery/openrecoveryscript"; if (!PartitionManager.Mount_By_Path(orsFile, false)) { - LOGINFO("Unable to mount %s for OpenRecoveryScript support.\n", TWFunc::get_cache_dir().c_str()); - gui_msg(Msg(msg::kError, "unable_to_mount=Unable to mount {1}")(TWFunc::get_cache_dir())); + LOGINFO("Unable to mount %s for OpenRecoveryScript support.\n", logDir.c_str()); + gui_msg(Msg(msg::kError, "unable_to_mount=Unable to mount {1}")(logDir.c_str())); return 0; } if (TWFunc::Path_Exists(orsFile)) { @@ -148,8 +154,9 @@ 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, 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, "system") == 0 || strcmp(value, "/system") == 0 || strcmp(value, PartitionManager.Get_Android_Root_Path().c_str()) == 0) { + PartitionManager.Wipe_By_Path("/system"); + PartitionManager.Update_System_Details(); } 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) { @@ -158,6 +165,14 @@ int OpenRecoveryScript::run_script_file(void) { LOGERR("Error with wipe command value: '%s'\n", value); ret_val = 1; } + } else if (strcmp(command, "format") == 0) { + // Format + if (strcmp(value, "data") == 0 || strcmp(value, "/data") == 0 || strcmp(value, "factory") == 0 || strcmp(value, "factoryreset") == 0) { + PartitionManager.Format_Data(); + } else { + LOGERR("Error with format command value: '%s'\n", value); + ret_val = 1; + } } else if (strcmp(command, "backup") == 0) { // Backup DataManager::SetValue("tw_action_text2", gui_parse_text("{@backing}")); @@ -301,6 +316,8 @@ int OpenRecoveryScript::run_script_file(void) { strcat(mount, value); } else strcpy(mount, value); + if (!strcmp(mount, "/system")) + strcpy(mount, PartitionManager.Get_Android_Root_Path().c_str()); if (PartitionManager.Mount_By_Path(mount, true)) gui_msg(Msg("mounted=Mounted '{1}'")(mount)); } else if (strcmp(command, "unmount") == 0 || strcmp(command, "umount") == 0) { @@ -311,6 +328,8 @@ int OpenRecoveryScript::run_script_file(void) { strcat(mount, value); } else strcpy(mount, value); + if (!strcmp(mount, "/system")) + strcpy(mount, PartitionManager.Get_Android_Root_Path().c_str()); if (PartitionManager.UnMount_By_Path(mount, true)) gui_msg(Msg("unmounted=Unounted '{1}'")(mount)); } else if (strcmp(command, "set") == 0) { @@ -345,6 +364,8 @@ int OpenRecoveryScript::run_script_file(void) { TWFunc::tw_reboot(rb_download); else if (strlen(value) && strcmp(value, "edl") == 0) TWFunc::tw_reboot(rb_edl); + else if (strlen(value) && strcmp(value, "hacked_bl") == 0) + TWFunc::tw_reboot(rb_hacked_bl); else TWFunc::tw_reboot(rb_system); } else if (strcmp(command, "cmd") == 0) { @@ -377,6 +398,7 @@ int OpenRecoveryScript::run_script_file(void) { } else { ret_val = 1; // failure } + PartitionManager.Update_System_Details(); sideload = 1; // Causes device to go to the home screen afterwards if (sideload_child_pid != 0) { LOGINFO("Signaling child sideload process to exit.\n"); @@ -395,13 +417,22 @@ int OpenRecoveryScript::run_script_file(void) { if (ret_val != 0) ret_val = 1; // failure } else if (strcmp(command, "decrypt") == 0) { + // twrp cmd cannot decrypt a password with space, should decrypt on gui if (*value) { - ret_val = PartitionManager.Decrypt_Device(value); + string tmp = value; + std::vector args = TWFunc::Split_String(tmp, " "); + + string pass = args[0]; + string userid = "0"; + if (args.size() > 1) + userid = args[1]; + + ret_val = PartitionManager.Decrypt_Device(pass, atoi(userid.c_str())); if (ret_val != 0) - ret_val = 1; // failure + ret_val = 1; // failure } else { gui_err("no_pwd=No password provided."); - ret_val = 1; // failure + ret_val = 1; // failure } } else { LOGERR("Unrecognized script command: '%s'\n", command); @@ -412,23 +443,28 @@ int OpenRecoveryScript::run_script_file(void) { unlink(SCRIPT_FILE_TMP); gui_msg("done_ors=Done processing script file"); } else { - gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(SCRIPT_FILE_TMP)(strerror(errno))); + gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(SCRIPT_FILE_TMP)( + strerror(errno))); return 1; } - if (install_cmd && DataManager::GetIntValue(TW_HAS_INJECTTWRP) == 1 && DataManager::GetIntValue(TW_INJECT_AFTER_ZIP) == 1) { + if (install_cmd && DataManager::GetIntValue(TW_HAS_INJECTTWRP) == 1 && + DataManager::GetIntValue(TW_INJECT_AFTER_ZIP) == 1) { gui_msg("injecttwrp=Injecting TWRP into boot image..."); TWPartition* Boot = PartitionManager.Find_Partition_By_Path("/boot"); if (Boot == NULL || Boot->Current_File_System != "emmc") - TWFunc::Exec_Cmd("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash"); + TWFunc::Exec_Cmd( + "injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash"); else { - string injectcmd = "injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash bd=" + Boot->Actual_Block_Device; + string injectcmd = + "injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash bd=" + + Boot->Actual_Block_Device; TWFunc::Exec_Cmd(injectcmd.c_str()); } gui_msg("done=Done."); } if (sideload) - ret_val = 1; // Forces booting to the home page after sideload + ret_val = 1; // Forces booting to the home page after sideload return ret_val; } @@ -641,26 +677,51 @@ int OpenRecoveryScript::Run_OpenRecoveryScript_Action() { // this is called by the "twcmd" GUI action when a command is received via FIFO from the "twrp" command line tool void OpenRecoveryScript::Run_CLI_Command(const char* command) { - if (strlen(command) > 11 && strncmp(command, "runscript", 9) == 0) { - const char* filename = command + 10; - if (OpenRecoveryScript::copy_script_file(filename) == 0) { - LOGINFO("Unable to copy script file\n"); + string tmp = command; + std::vector parts = + TWFunc::Split_String(tmp, " "); // pats[0] is cmd, parts[1...] is args + string cmd_str = parts[0]; + + if (cmd_str == "runscript") { + if (parts.size() > 1) { + string filename = parts[1]; + if (OpenRecoveryScript::copy_script_file(filename) == 0) { + LOGINFO("Unable to copy script file\n"); + } else { + OpenRecoveryScript::run_script_file(); + } + } else { + LOGINFO("Missing parameter: script file name\n"); + } + } else if (cmd_str == "get") { + if (parts.size() > 1) { + string varname = parts[1]; + string value; + DataManager::GetValue(varname, value); + gui_print("%s = %s\n", varname.c_str(), value.c_str()); } else { - OpenRecoveryScript::run_script_file(); + LOGINFO("Missing parameter: var name\n"); } - } else if (strlen(command) > 5 && strncmp(command, "get", 3) == 0) { - const char* varname = command + 4; - string value; - DataManager::GetValue(varname, value); - gui_print("%s = %s\n", varname, value.c_str()); - } else if (strlen(command) > 9 && strncmp(command, "decrypt", 7) == 0) { - const char* pass = command + 8; - gui_msg("decrypt_cmd=Attempting to decrypt data partition via command line."); - if (PartitionManager.Decrypt_Device(pass) == 0) { - // set_page_done = 1; // done by singleaction_page anyway - std::string orsFile = TWFunc::get_cache_dir() + "/openrecoveryscript"; - if (TWFunc::Path_Exists(orsFile)) { - Run_OpenRecoveryScript_Action(); + } else if (cmd_str == "decrypt") { + // twrp cmd cannot decrypt a password with space, should decrypt on gui + if (parts.size() == 1) { + gui_err("no_pwd=No password provided."); + } else { + string pass = parts[1]; + string userid = "0"; + if (parts.size() > 2) + userid = parts[2]; + + gui_msg("decrypt_cmd=Attempting to decrypt data partition or user data via command line."); + if (PartitionManager.Decrypt_Device(pass, atoi(userid.c_str())) == 0) { + // set_page_done = 1; // done by singleaction_page anyway + std::string logDir = TWFunc::get_log_dir(); + if (logDir == DATA_LOGS_DIR) + logDir = "/data/cache"; + std::string orsFile = logDir + "/openrecoveryscript"; + if (TWFunc::Path_Exists(orsFile)) { + Run_OpenRecoveryScript_Action(); + } } } } else if (OpenRecoveryScript::Insert_ORS_Command(command)) { diff --git a/orscmd/orscmd.cpp b/orscmd/orscmd.cpp index c47c0f67f6..62fefd4453 100644 --- a/orscmd/orscmd.cpp +++ b/orscmd/orscmd.cpp @@ -43,9 +43,10 @@ void print_usage(void) { printf(" backup [backupname]\n"); printf(" restore [backupname]\n"); printf(" wipe \n"); + printf(" format data\n"); printf(" sideload\n"); printf(" set [value]\n"); - printf(" decrypt \n"); + printf(" decrypt [USER ID]\n"); printf(" remountrw\n"); printf(" fixperms\n"); printf(" mount \n"); diff --git a/ozip_decrypt/Android.mk b/ozip_decrypt/Android.mk new file mode 100644 index 0000000000..161cae88ce --- /dev/null +++ b/ozip_decrypt/Android.mk @@ -0,0 +1,11 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := ozip_decrypt +LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := ozip_decrypt.cpp +LOCAL_C_INCLUDES := external/boringssl/src/include +LOCAL_SHARED_LIBRARIES := libcrypto +include $(BUILD_EXECUTABLE) diff --git a/ozip_decrypt/ozip_decrypt.cpp b/ozip_decrypt/ozip_decrypt.cpp new file mode 100644 index 0000000000..97826ec192 --- /dev/null +++ b/ozip_decrypt/ozip_decrypt.cpp @@ -0,0 +1,152 @@ +/* + Copyright 2020 Mauronofrio + + This file 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. + + This file 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. + + GNU General Public License . +*/ + +#include +#include +#include +#include +#define _FILE_OFFSET_BITS 64 +//extern "C" __int64 __cdecl _ftelli64(FILE*); + +using namespace std; +typedef std::basic_string u_string; + +int decrypt(unsigned char* ciphertext, int ciphertext_len, unsigned char* key, + unsigned char* iv, unsigned char* plaintext) +{ + EVP_CIPHER_CTX* ctx; + int len; + int plaintext_len; + ctx = EVP_CIPHER_CTX_new(); + EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, iv); + EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len); + plaintext_len = len; + EVP_DecryptFinal_ex(ctx, plaintext + len, &len); + plaintext_len += len; + EVP_CIPHER_CTX_free(ctx); + return plaintext_len; +} + +std::string hexToASCII(string hex) +{ + int len = hex.length(); + std::string newString; + for (int i = 0; i < len; i += 2) + { + string byte = hex.substr(i, 2); + char chr = (char)(int)strtol(byte.c_str(), nullptr, 16); + newString.push_back(chr); + } + return newString; +} + +bool testkey(const char* keyf, const char* path) { + u_string key = (unsigned char*)(hexToASCII(keyf)).c_str(); + int data[17]; + FILE* fps = fopen(path, "rb"); + fseek(fps, 4176, SEEK_SET); + fread(data, sizeof(char), 16, fps); + fclose(fps); + u_string udata = (unsigned char*)data; + EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); + EVP_CIPHER_CTX_init(ctx); + EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key.c_str(), NULL); + EVP_CIPHER_CTX_set_padding(ctx, false); + unsigned char buffer[1024], * pointer = buffer; + int outlen; + EVP_DecryptUpdate(ctx, pointer, &outlen, udata.c_str(), udata.length()); + pointer += outlen; + EVP_DecryptFinal_ex(ctx, pointer, &outlen); + pointer += outlen; + EVP_CIPHER_CTX_free(ctx); + u_string test= u_string(buffer, pointer - buffer); + u_string checktest = test.substr(0, 4); + if (checktest == ((unsigned char*) "\x50\x4B\x03\x04") || checktest == ((unsigned char*) "\x41\x4E\x44\x52")) { + return true; + } + return false; +} + +int main(int argc, char* argv[]) +{ + + if (argc != 3) + { + printf("Usage: ozipdecrypt key [*.ozip]\n"); + return 0; + } + const char* key = argv[1]; + const char* path = argv[2]; + FILE* fp = fopen(path, "rb"); + char magic[13]; + fgets(magic, sizeof(magic), fp); + string temp(path); + temp = (temp.substr(0, temp.size() - 5)).append(".zip"); + const char* destpath= temp.c_str(); + if (strcmp(magic, "OPPOENCRYPT!") != 0) + { + printf("This is not an .ozip file!\n"); + fclose(fp); + int rencheck = rename(path, destpath); + if (rencheck == 0) { + printf("Renamed .ozip file in .zip file\n"); + } + else + { + printf("Unable to rename .ozip file in .zip file\n"); + } + return 0; + } + if (testkey(key, path) == false) + { + printf("Key is not good!\n"); + fclose(fp); + return 0; + } + else { + printf("Key is good!\n"); + } + FILE* fp2 = fopen(destpath, "wb"); + fseek(fp, 0L, SEEK_END); + unsigned long int sizetot = ftello(fp); + fseek(fp, 4176, SEEK_SET); + int bdata[16384]; + unsigned long int sizeseek; + printf("Decrypting...\n"); + while (true) + { + unsigned char data[17]; + fread(data, sizeof(char), 16, fp); + decrypt(data, sizeof(data), (unsigned char*)(hexToASCII(key)).c_str(), NULL, data); + fwrite(data, sizeof(char), 16, fp2); + sizeseek = ftello(fp); + if ((sizetot - sizeseek) <= 16384) { + fread(bdata, sizeof(char), (sizetot - sizeseek), fp); + fwrite(bdata, sizeof(char), (sizetot - sizeseek), fp2); + break; + } + else + { + fread(bdata, sizeof(char), 16384, fp); + fwrite(bdata, sizeof(char), 16384, fp2); + } + } + printf("File succesfully decrypted, saved in %s\n", destpath); + fclose(fp2); + fclose(fp); + return 0; +} + diff --git a/partition.cpp b/partition.cpp old mode 100644 new mode 100755 index aa82c09ec2..33b37a9cf2 --- a/partition.cpp +++ b/partition.cpp @@ -1,5 +1,5 @@ /* - Copyright 2013 to 2017 TeamWin + Copyright 2013 to 2020 TeamWin This file is part of TWRP/TeamWin Recovery Project. TWRP is free software: you can redistribute it and/or modify @@ -19,17 +19,20 @@ #include #include #include +#include +#include #include +#include #include -#include #include #include +#include +#include +#include #include +#include #include -#include #include -#include -#include #include "cutils/properties.h" #include "libblkid/include/blkid.h" @@ -158,6 +161,9 @@ enum TW_FSTAB_FLAGS { TWFLAG_FORMATTABLE, TWFLAG_RESIZE, TWFLAG_KEYDIRECTORY, + TWFLAG_WRAPPEDKEY, + TWFLAG_ADOPTED_MOUNT_DELAY, + TWFLAG_DM_USE_ORIGINAL_PATH, }; /* Flags without a trailing '=' are considered dual format flags and can be @@ -202,6 +208,9 @@ const struct flag_list tw_flags[] = { { "formattable", TWFLAG_FORMATTABLE }, { "resize", TWFLAG_RESIZE }, { "keydirectory=", TWFLAG_KEYDIRECTORY }, + { "wrappedkey", TWFLAG_WRAPPEDKEY }, + { "adopted_mount_delay=", TWFLAG_ADOPTED_MOUNT_DELAY }, + { "dm_use_original_path", TWFLAG_DM_USE_ORIGINAL_PATH }, { 0, 0 }, }; @@ -266,13 +275,16 @@ TWPartition::TWPartition() { Adopted_GUID = ""; SlotSelect = false; Key_Directory = ""; + Adopted_Mount_Delay = 0; + Original_Path = ""; + Use_Original_Path = false; } TWPartition::~TWPartition(void) { // Do nothing } -bool TWPartition::Process_Fstab_Line(const char *fstab_line, bool Display_Error, std::map *twrp_flags) { +bool TWPartition::Process_Fstab_Line(const char *fstab_line, bool Display_Error, std::map *twrp_flags, bool Sar_Detect) { char full_line[MAX_FSTAB_LINE_LENGTH]; char twflags[MAX_FSTAB_LINE_LENGTH] = ""; char* ptr; @@ -309,11 +321,12 @@ bool TWPartition::Process_Fstab_Line(const char *fstab_line, bool Display_Error, Mount_Point = ptr; if (fstab_version == 2) { additional_entry = PartitionManager.Find_Partition_By_Path(Mount_Point); - if (additional_entry) { + if (!Sar_Detect && additional_entry) { LOGINFO("Found an additional entry for '%s'\n", Mount_Point.c_str()); } } - LOGINFO("Processing '%s'\n", Mount_Point.c_str()); + if(!Sar_Detect) + LOGINFO("Processing '%s'\n", Mount_Point.c_str()); Backup_Path = Mount_Point; Storage_Path = Mount_Point; Display_Name = ptr + 1; @@ -346,7 +359,8 @@ bool TWPartition::Process_Fstab_Line(const char *fstab_line, bool Display_Error, return false; } else { Primary_Block_Device = ptr; - Find_Real_Block_Device(Primary_Block_Device, Display_Error); + if (PartitionManager.Get_Android_Root_Path() != "/system_root") + Find_Real_Block_Device(Primary_Block_Device, Display_Error); } item_index++; } else if (item_index > 2) { @@ -410,13 +424,19 @@ bool TWPartition::Process_Fstab_Line(const char *fstab_line, bool Display_Error, if (Primary_Block_Device.find("*") != string::npos) Wildcard_Block_Device = true; - if (Mount_Point == "auto") { + if (Sar_Detect) { + if(Is_File_System(Fstab_File_System) && (Mount_Point == "/" || Mount_Point == "/system" || Mount_Point == "/system_root")) + Find_Actual_Block_Device(); + else + return true; + } else if (Mount_Point == "auto") { Mount_Point = "/auto"; char autoi[5]; sprintf(autoi, "%i", auto_index); Mount_Point += autoi; Backup_Path = Mount_Point; Storage_Path = Mount_Point; + Backup_Name = Mount_Point.substr(1); auto_index++; Setup_File_System(Display_Error); Display_Name = "Storage"; @@ -436,8 +456,10 @@ 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 == PartitionManager.Get_Android_Root_Path()) { + Backup_Name = Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1); + if (Mount_Point == "/" || Mount_Point == "/system" || Mount_Point == "/system_root") { Display_Name = "System"; + Backup_Name = "system"; Backup_Display_Name = Display_Name; Storage_Name = Display_Name; Wipe_Available_in_GUI = true; @@ -591,13 +613,25 @@ bool TWPartition::Process_Fstab_Line(const char *fstab_line, bool Display_Error, bool mounted = Is_Mounted(); if (mounted || Mount(false)) { // Read the backup settings file - DataManager::LoadPersistValues(); TWFunc::Fixup_Time_On_Boot("/persist/time/"); if (!mounted) UnMount(false); } } + if (Is_File_System(Fstab_File_System) && (Mount_Point == "/" || Mount_Point == "/system" || Mount_Point == "/system_root")) { + if (Sar_Detect) { + Mount_Point = "/s"; + Mount_Read_Only = true; + Can_Be_Mounted = true; + } else { + Mount_Point = PartitionManager.Get_Android_Root_Path(); + Backup_Path = Mount_Point; + Storage_Path = Mount_Point; + Make_Dir(Mount_Point, Display_Error); + } + } + return true; } @@ -630,17 +664,20 @@ void TWPartition::Setup_Data_Partition(bool Display_Error) { DataManager::SetValue(TW_IS_DECRYPTED, 1); Is_Encrypted = true; Is_Decrypted = true; - if (Key_Directory.empty()) + if (Key_Directory.empty()) { Is_FBE = false; - else + DataManager::SetValue(TW_IS_FBE, 0); + } else { Is_FBE = true; - DataManager::SetValue(TW_IS_FBE, 0); + DataManager::SetValue(TW_IS_FBE, 1); + } Decrypted_Block_Device = crypto_blkdev; LOGINFO("Data already decrypted, new block device: '%s'\n", crypto_blkdev); } else if (!Mount(false)) { if (Is_Present) { if (Key_Directory.empty()) { - set_partition_data(Actual_Block_Device.c_str(), Crypto_Key_Location.c_str(), Fstab_File_System.c_str()); + set_partition_data(Use_Original_Path ? Original_Path.c_str() : 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; @@ -649,6 +686,7 @@ void TWPartition::Setup_Data_Partition(bool Display_Error) { Setup_Image(); DataManager::SetValue(TW_IS_ENCRYPTED, 1); DataManager::SetValue(TW_CRYPTO_PWTYPE, cryptfs_get_password_type()); + DataManager::SetValue("tw_crypto_pwtype_0", cryptfs_get_password_type()); DataManager::SetValue(TW_CRYPTO_PASSWORD, ""); DataManager::SetValue("tw_crypto_display", ""); } else { @@ -659,16 +697,25 @@ void TWPartition::Setup_Data_Partition(bool Display_Error) { Is_Decrypted = false; } } 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()); + LOGERR("Primary block device '%s' for mount point '%s' is not present!\n", + Primary_Block_Device.c_str(), Mount_Point.c_str()); } } else { - - if (!Decrypt_FBE_DE()) { - LOGINFO("Trying wrapped key.\n"); - property_set("fbe.data.wrappedkey", "true"); + int is_device_fbe; + DataManager::GetValue(TW_IS_FBE, is_device_fbe); + if (!Decrypt_FBE_DE() && is_device_fbe == 1) { + char wrappedvalue[PROPERTY_VALUE_MAX]; + property_get("fbe.data.wrappedkey", wrappedvalue, ""); + std::string wrappedkeyvalue(wrappedvalue); + if (wrappedkeyvalue == "true") { + LOGERR("Unable to decrypt FBE device\n"); + } else { + LOGINFO("Trying wrapped key.\n"); + property_set("fbe.data.wrappedkey", "true"); if (!Decrypt_FBE_DE()) { - LOGERR("Unable to decrypt FBE device\n"); + LOGINFO("Unable to decrypt device\n"); } + } } } if (datamedia && (!Is_Encrypted || (Is_Encrypted && Is_Decrypted))) { @@ -685,52 +732,62 @@ void TWPartition::Setup_Data_Partition(bool Display_Error) { bool TWPartition::Decrypt_FBE_DE() { if (TWFunc::Path_Exists("/data/unencrypted/key/version")) { + DataManager::SetValue(TW_IS_FBE, 1); + PartitionManager.Set_Crypto_State(); + PartitionManager.Set_Crypto_Type("file"); 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 + Is_FBE = true; + ExcludeAll(Mount_Point + "/convert_fbe"); + ExcludeAll(Mount_Point + "/unencrypted"); + ExcludeAll(Mount_Point + "/misc/vold/user_keys"); + 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-wal"); + 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 + ExcludeAll(Mount_Point + "/system/users/0/gatekeeper.password.key"); + ExcludeAll(Mount_Point + "/system/users/0/gatekeeper.pattern.key"); + int retry_count = 3; + while (!Decrypt_DE() && --retry_count) + usleep(2000); + if (retry_count > 0) { + PartitionManager.Set_Crypto_State(); + Is_Encrypted = true; + Is_Decrypted = false; + 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 + } + PartitionManager.Parse_Users(); // after load_all_de_keys() to parse_users + std::vector::iterator iter; + std::vector* userList = PartitionManager.Get_Users_List(); + for (iter = userList->begin(); iter != userList->end(); iter++) { + if (atoi((*iter).userId.c_str()) != 0) { + ExcludeAll(Mount_Point + "/system_de/" + (*iter).userId + "/spblob"); + ExcludeAll(Mount_Point + "/system/users/" + (*iter).userId + "/gatekeeper.password.key"); + ExcludeAll(Mount_Point + "/system/users/" + (*iter).userId + "/gatekeeper.pattern.key"); + ExcludeAll(Mount_Point + "/system/users/" + (*iter).userId + "/locksettings.db"); + ExcludeAll(Mount_Point + "/system/users/" + (*iter).userId + "/locksettings.db-wal"); } - DataManager::SetValue(TW_CRYPTO_PWTYPE, pwd_type); - DataManager::SetValue(TW_CRYPTO_PASSWORD, ""); - DataManager::SetValue("tw_crypto_display", ""); - return true; } + DataManager::SetValue(TW_CRYPTO_PWTYPE, pwd_type); + DataManager::SetValue("tw_crypto_pwtype_0", 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 } + DataManager::SetValue(TW_IS_FBE, 0); return false; } @@ -864,6 +921,13 @@ void TWPartition::Apply_TW_Flag(const unsigned flag, const char* str, const bool LOGINFO("FBE contents '%s', filenames '%s'\n", FBE_contents.c_str(), FBE_filenames.c_str()); } break; + case TWFLAG_WRAPPEDKEY: + // Set fbe.data.wrappedkey to true + { + property_set("fbe.data.wrappedkey", "true"); + LOGINFO("FBE wrapped key enabled\n"); + } + break; case TWFLAG_FLASHIMG: Can_Flash_Img = val; break; @@ -930,8 +994,13 @@ void TWPartition::Apply_TW_Flag(const unsigned flag, const char* str, const bool case TWFLAG_ALTDEVICE: Alternate_Block_Device = str; break; + case TWFLAG_ADOPTED_MOUNT_DELAY: + Adopted_Mount_Delay = atoi(str); + break; case TWFLAG_KEYDIRECTORY: Key_Directory = str; + case TWFLAG_DM_USE_ORIGINAL_PATH: + Use_Original_Path = true; default: // Should not get here LOGINFO("Flag identified for processing, but later unmatched: %i\n", flag); @@ -1073,8 +1142,6 @@ void TWPartition::Setup_File_System(bool Display_Error) { // Make the mount point folder if it doesn't exist Make_Dir(Mount_Point, Display_Error); - Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1); - Backup_Name = Display_Name; Backup_Method = BM_FILES; } @@ -1128,10 +1195,24 @@ void TWPartition::Setup_Data_Media() { DataManager::SetValue("tw_has_internal", 1); DataManager::SetValue("tw_has_data_media", 1); backup_exclusions.add_absolute_dir("/data/data/com.google.android.music/files"); + backup_exclusions.add_absolute_dir("/data/per_boot"); // DJ9,14Jan2020 - exclude this dir to prevent "error 255" on AOSP ROMs that create and lock it + backup_exclusions.add_absolute_dir("/data/vendor/dumpsys"); + backup_exclusions.add_absolute_dir("/data/cache"); wipe_exclusions.add_absolute_dir(Mount_Point + "/misc/vold"); // adopted storage keys ExcludeAll(Mount_Point + "/.layout_version"); ExcludeAll(Mount_Point + "/system/storage.xml"); } else { + int i; + string path; + for (i = 2; i <= 9; i++) { + path = "/sdcard" + TWFunc::to_string(i); + if (!TWFunc::Path_Exists(path)) { + Make_Dir(path, false); + Symlink_Mount_Point = path; + LOGINFO("'%s' data/media emulated storage symlinked to %s.\n", Mount_Point.c_str(), Symlink_Mount_Point.c_str()); + break; + } + } if (Mount(true) && TWFunc::Path_Exists(Mount_Point + "/media/0")) { Storage_Path = Mount_Point + "/media/0"; Symlink_Path = Storage_Path; @@ -1144,6 +1225,8 @@ void TWPartition::Setup_Data_Media() { void TWPartition::Find_Real_Block_Device(string& Block, bool Display_Error) { char device[PATH_MAX], realDevice[PATH_MAX]; + Original_Path = Block; + strcpy(device, Block.c_str()); memset(realDevice, 0, sizeof(realDevice)); while (readlink(device, realDevice, sizeof(realDevice)) > 0) @@ -1406,7 +1489,7 @@ bool TWPartition::Mount(bool Display_Error) { string cmd = "/sbin/exfat-fuse -o big_writes,max_read=131072,max_write=131072 " + Actual_Block_Device + " " + Mount_Point; LOGINFO("cmd: %s\n", cmd.c_str()); string result; - if (TWFunc::Exec_Cmd(cmd, result) != 0) { + if (TWFunc::Exec_Cmd(cmd, result, false) != 0) { LOGINFO("exfat-fuse failed to mount with result '%s', trying vfat\n", result.c_str()); Current_File_System = "vfat"; } else { @@ -1524,10 +1607,23 @@ bool TWPartition::Mount(bool Display_Error) { string Command = "mount -o bind '" + Symlink_Path + "' '" + Symlink_Mount_Point + "'"; TWFunc::Exec_Cmd(Command); } + + if (Mount_Point == "/system_root") { + unlink("/system"); + mkdir("/system", 0755); + mount("/system_root/system", "/system", "auto", MS_BIND, NULL); + } + return true; } bool TWPartition::UnMount(bool Display_Error) { + if (Mount_Point == "/system_root") { + if (umount("/system") == -1) + umount2("/system", MNT_DETACH); + rmdir("/system"); + symlink("/system_root/system", "/system"); + } if (Is_Mounted()) { int never_unmount_system; @@ -1594,6 +1690,12 @@ bool TWPartition::Wipe(string New_File_System) { if (Mount_Point == "/cache") Log_Offset = 0; + if (Mount_Point == PartitionManager.Get_Android_Root_Path()) { + if (tw_get_default_metadata(PartitionManager.Get_Android_Root_Path().c_str()) != 0) { + gui_msg(Msg(msg::kWarning, "restore_system_context=Unable to get default context for {1} -- Android may not boot.")(PartitionManager.Get_Android_Root_Path())); + } + } + if (Retain_Layout_Version && Mount(false) && TWFunc::Path_Exists(Layout_Filename)) TWFunc::copy_file(Layout_Filename, "/.layout_version", 0600); else @@ -1601,6 +1703,11 @@ bool TWPartition::Wipe(string New_File_System) { if (Has_Data_Media && Current_File_System == New_File_System) { wiped = Wipe_Data_Without_Wiping_Media(); + if (Mount_Point == "/data" && TWFunc::get_log_dir() == DATA_LOGS_DIR) { + bool created = Recreate_Logs_Dir(); + if (!created) + LOGERR("Unable to create log directory for TWRP\n"); + } recreate_media = false; } else { DataManager::GetValue(TW_RM_RF_VAR, check); @@ -1630,9 +1737,12 @@ bool TWPartition::Wipe(string New_File_System) { } if (wiped) { - if (Mount_Point == "/cache") + if (Mount_Point == "/cache" && TWFunc::get_log_dir() != DATA_LOGS_DIR) DataManager::Output_Version(); + if (Mount_Point == PartitionManager.Get_Android_Root_Path()) { + tw_set_default_metadata(PartitionManager.Get_Android_Root_Path().c_str()); + } if (TWFunc::Path_Exists("/.layout_version") && Mount(false)) TWFunc::copy_file("/.layout_version", Layout_Filename, 0600); @@ -1650,10 +1760,7 @@ bool TWPartition::Wipe(string New_File_System) { } } - if (Has_Data_Media && recreate_media) { - Recreate_Media_Folder(); - } - if (Is_Storage && Mount(false)) + if (Is_Storage && Mount(false) && !Is_FBE) PartitionManager.Add_MTP_Storage(MTP_Storage_ID); } @@ -1944,10 +2051,10 @@ bool TWPartition::Wipe_Encryption() { gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name)); return false; } - if (!UnMount(true)) - goto exit; #ifdef TW_INCLUDE_CRYPTO + if (!UnMount(true)) + return false; if (Is_Decrypted && !Decrypted_Block_Device.empty()) { if (delete_crypto_blk_dev((char*)("userdata")) != 0) { LOGERR("Error deleting crypto block device, continuing anyway.\n"); @@ -1960,15 +2067,20 @@ bool TWPartition::Wipe_Encryption() { Is_Encrypted = false; if (Wipe(Fstab_File_System)) { Has_Data_Media = Save_Data_Media; - if (Has_Data_Media && !Symlink_Mount_Point.empty()) { - Recreate_Media_Folder(); - if (Mount(false)) - PartitionManager.Add_MTP_Storage(MTP_Storage_ID); - } DataManager::SetValue(TW_IS_ENCRYPTED, 0); #ifndef TW_OEM_BUILD gui_msg("format_data_msg=You may need to reboot recovery to be able to use /data again."); #endif + if (Is_FBE) { + gui_msg(Msg(msg::kWarning, "data_media_fbe_msg=TWRP will not recreate /data/media on an FBE device. Please reboot into your rom to create /data/media.")); + } else { + if (Has_Data_Media && !Symlink_Mount_Point.empty()) { + Recreate_Media_Folder(); + if (Mount(false)) + PartitionManager.Add_MTP_Storage(MTP_Storage_ID); + } + } + ret = true; if (!Key_Directory.empty()) ret = PartitionManager.Wipe_By_Path(Key_Directory); @@ -2002,6 +2114,7 @@ void TWPartition::Check_FS_Type() { if (blkid_do_fullprobe(pr)) { blkid_free_probe(pr); LOGINFO("Can't probe device %s\n", Actual_Block_Device.c_str()); + Current_File_System = ""; return; } @@ -2033,6 +2146,9 @@ void TWPartition::Check_FS_Type() { } bool TWPartition::Wipe_EXTFS(string File_System) { + if (!UnMount(true)) + return false; + #if PLATFORM_SDK_VERSION < 28 if (!TWFunc::Path_Exists("/sbin/mke2fs")) #else @@ -2172,11 +2288,10 @@ bool TWPartition::Wipe_EXT4() { bool TWPartition::Wipe_FAT() { string command; + if (!UnMount(true)) + return false; if (TWFunc::Path_Exists("/sbin/mkfs.fat")) { - if (!UnMount(true)) - return false; - gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkfs.fat")); Find_Actual_Block_Device(); command = "mkfs.fat " + Actual_Block_Device; @@ -2199,11 +2314,10 @@ bool TWPartition::Wipe_FAT() { bool TWPartition::Wipe_EXFAT() { string command; + if (!UnMount(true)) + return false; if (TWFunc::Path_Exists("/sbin/mkexfatfs")) { - if (!UnMount(true)) - return false; - gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkexfatfs")); Find_Actual_Block_Device(); command = "mkexfatfs " + Actual_Block_Device; @@ -2270,6 +2384,8 @@ bool TWPartition::Wipe_RMRF() { bool TWPartition::Wipe_F2FS() { string command; + if (!UnMount(true)) + return false; if (TWFunc::Path_Exists("/sbin/mkfs.f2fs")) { bool NeedPreserveFooter = true; @@ -2280,8 +2396,6 @@ bool TWPartition::Wipe_F2FS() { gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name)); return false; } - if (!UnMount(true)) - return false; /** * On decrypted devices, IOCTL_Get_Block_Size calculates size on device mapper, @@ -2355,6 +2469,9 @@ bool TWPartition::Wipe_NTFS() { string command; string Ntfsmake_Binary; + if (!UnMount(true)) + return false; + if (TWFunc::Path_Exists("/sbin/mkntfs")) Ntfsmake_Binary = "mkntfs"; else if (TWFunc::Path_Exists("/sbin/mkfs.ntfs")) @@ -2362,9 +2479,6 @@ bool TWPartition::Wipe_NTFS() { else return false; - if (!UnMount(true)) - return false; - gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)(Ntfsmake_Binary)); Find_Actual_Block_Device(); command = "/sbin/" + Ntfsmake_Binary + " " + Actual_Block_Device; @@ -2388,7 +2502,6 @@ bool TWPartition::Wipe_Data_Without_Wiping_Media() { if (!Mount(true)) return false; - gui_msg("wiping_data=Wiping data without wiping /data/media ..."); ret = Wipe_Data_Without_Wiping_Media_Func(Mount_Point + "/"); if (ret) @@ -2397,6 +2510,46 @@ bool TWPartition::Wipe_Data_Without_Wiping_Media() { #endif // ifdef TW_OEM_BUILD } +bool TWPartition::Recreate_Logs_Dir() { +#ifdef TW_INCLUDE_FBE + struct passwd pd; + struct passwd *pwdptr = &pd; + struct passwd *tempPd; + char pwdBuf[512]; + int uid = 0, gid = 0; + + if ((getpwnam_r("system", pwdptr, pwdBuf, sizeof(pwdBuf), &tempPd)) != 0) { + LOGERR("unable to get system user id\n"); + return false; + } else { + struct group grp; + struct group *grpptr = &grp; + struct group *tempGrp; + char grpBuf[512]; + + if ((getgrnam_r("cache", grpptr, grpBuf, sizeof(grpBuf), &tempGrp)) != 0) { + LOGERR("unable to get cache group id\n"); + return false; + } else { + uid = pd.pw_uid; + gid = grp.gr_gid; + std::string abLogsRecoveryDir(DATA_LOGS_DIR); + abLogsRecoveryDir += "/recovery/"; + + if (!TWFunc::Create_Dir_Recursive(abLogsRecoveryDir, S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP, uid, gid)) { + LOGERR("Unable to recreate %s\n", abLogsRecoveryDir.c_str()); + return false; + } + if (setfilecon(abLogsRecoveryDir.c_str(), "u:object_r:cache_file:s0") != 0) { + LOGERR("Unable to set contexts for %s\n", abLogsRecoveryDir.c_str()); + return false; + } + } + } +#endif + return true; +} + bool TWPartition::Wipe_Data_Without_Wiping_Media_Func(const string& parent __unused) { string dir; @@ -2510,6 +2663,22 @@ bool TWPartition::Backup_Tar(PartitionSettings *part_settings, pid_t *tar_fork_p Full_FileName = part_settings->Backup_Folder + "/" + Backup_FileName; if (Has_Data_Media) gui_msg(Msg(msg::kWarning, "backup_storage_warning=Backups of {1} do not include any files in internal storage such as pictures or downloads.")(Display_Name)); + if (Mount_Point == "/data" && DataManager::GetIntValue(TW_IS_FBE)) { + std::vector::iterator iter; + std::vector* userList = PartitionManager.Get_Users_List(); + for (iter = userList->begin(); iter != userList->end(); iter++) { + if (!(*iter).isDecrypted && (*iter).userId != "0") { + gui_msg(Msg(msg::kWarning, + "backup_storage_undecrypt_warning=Backup will not include some files from user {1} " + "because the user is not decrypted.")((*iter).userId)); + backup_exclusions.add_absolute_dir("/data/system_ce/" + (*iter).userId); + backup_exclusions.add_absolute_dir("/data/misc_ce/" + (*iter).userId); + backup_exclusions.add_absolute_dir("/data/vendor_ce/" + (*iter).userId); + backup_exclusions.add_absolute_dir("/data/media/" + (*iter).userId); + backup_exclusions.add_absolute_dir("/data/user/" + (*iter).userId); + } + } + } tar.part_settings = part_settings; tar.backup_exclusions = &backup_exclusions; tar.setdir(Backup_Path); @@ -2894,7 +3063,7 @@ bool TWPartition::Find_Wildcard_Block_Devices(const string& Device) { TWPartition *part = new TWPartition; char buffer[MAX_FSTAB_LINE_LENGTH]; sprintf(buffer, "%s %s-%i auto defaults defaults", item.c_str(), Mount_Point.c_str(), ++mount_point_index); - part->Process_Fstab_Line(buffer, false, NULL); + part->Process_Fstab_Line(buffer, false, NULL, false); char display[MAX_FSTAB_LINE_LENGTH]; sprintf(display, "%s %i", Storage_Name.c_str(), mount_point_index); part->Storage_Name = display; @@ -3187,7 +3356,14 @@ int TWPartition::Decrypt_Adopted() { char type_guid[80]; char part_guid[80]; - if (gpt_disk_get_partition_info(fd, 2, type_guid, part_guid) == 0) { + uint32_t p_num; + size_t last_digit = Primary_Block_Device.find_last_not_of("0123456789"); + if ((last_digit != string::npos) && (last_digit != Primary_Block_Device.length()-1)) + p_num = atoi(Primary_Block_Device.substr(last_digit + 1).c_str()) + 1; + else + p_num = 2; + + if (gpt_disk_get_partition_info(fd, p_num, type_guid, part_guid) == 0) { LOGINFO("type: '%s'\n", type_guid); LOGINFO("part: '%s'\n", part_guid); Adopted_GUID = part_guid; @@ -3203,16 +3379,22 @@ int TWPartition::Decrypt_Adopted() { * to disable USB Mass Storage whenever adopted storage * is present. */ - LOGINFO("Detected adopted storage, disabling USB mass storage mode\n"); - DataManager::SetValue("tw_has_usb_storage", 0); + if (p_num == 2) { + // TODO: Properly detect mixed vs fully adopted storage. Maybe this + // should be moved to partitionmanager instead, and disable after + // checking all partitions. Also the presence of adopted storage does + // not necessarily mean it's being used as Internal Storage + LOGINFO("Detected adopted storage, disabling USB mass storage mode\n"); + DataManager::SetValue("tw_has_usb_storage", 0); + } } } } if (Is_Adopted_Storage) { - string Adopted_Block_Device = Alternate_Block_Device + "p2"; + string Adopted_Block_Device = Alternate_Block_Device + "p" + TWFunc::to_string(p_num); if (!TWFunc::Path_Exists(Adopted_Block_Device)) { - Adopted_Block_Device = Alternate_Block_Device + "2"; + Adopted_Block_Device = Alternate_Block_Device + TWFunc::to_string(p_num); if (!TWFunc::Path_Exists(Adopted_Block_Device)) { LOGINFO("Adopted block device does not exist\n"); goto exit; @@ -3327,3 +3509,16 @@ void TWPartition::Set_Backup_FileName(string fname) { string TWPartition::Get_Backup_Name() { return Backup_Name; } + +std::string TWPartition::Get_Backup_FileName() { + return Backup_FileName; +} + +std::string TWPartition::Get_Display_Name() { + return Display_Name; +} + +bool TWPartition::Is_SlotSelect() { + return SlotSelect; + +} diff --git a/partitionmanager.cpp b/partitionmanager.cpp index 41d8af209c..7374e522e2 100755 --- a/partitionmanager.cpp +++ b/partitionmanager.cpp @@ -52,7 +52,9 @@ #include "gui/gui.hpp" #include "progresstracking.hpp" #include "twrpDigestDriver.hpp" +#include "twrpRepacker.hpp" #include "adbbu/libtwadbbu.hpp" +#include "amonet.h" #ifdef TW_HAS_MTP #ifdef TW_HAS_LEGACY_MTP @@ -72,18 +74,18 @@ extern "C" { } #ifdef TW_INCLUDE_CRYPTO - #include "crypto/fde/cryptfs.h" - #include "gui/rapidxml.hpp" - #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" - #endif +#include "crypto/fde/cryptfs.h" +#include "gui/rapidxml.hpp" +#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" +#endif #endif #ifdef AB_OTA_UPDATER @@ -92,6 +94,7 @@ extern "C" { #endif extern bool datamedia; +std::vector Users_List; TWPartitionManager::TWPartitionManager(void) { mtp_was_enabled = false; @@ -111,7 +114,24 @@ TWPartitionManager::TWPartitionManager(void) { #endif } -int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error) { +void TWPartitionManager::Set_Crypto_State() { + char crypto_state[PROPERTY_VALUE_MAX]; + property_get("ro.crypto.state", crypto_state, "error"); + if (strcmp(crypto_state, "error") == 0) + property_set("ro.crypto.state", "encrypted"); +} + +int TWPartitionManager::Set_Crypto_Type(const char* crypto_type) { + char type_prop[PROPERTY_VALUE_MAX]; + property_get("ro.crypto.type", type_prop, "error"); + if (strcmp(type_prop, "error") == 0) + property_set("ro.crypto.type", crypto_type); + // Sleep for a bit so that services can start if needed + sleep(1); + return 0; +} + +int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error, bool Sar_Detect) { FILE *fstabFile; char fstab_line[MAX_FSTAB_LINE_LENGTH]; TWPartition* settings_partition = NULL; @@ -198,7 +218,7 @@ int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error) fstab_line[line_size] = '\n'; TWPartition* partition = new TWPartition(); - if (partition->Process_Fstab_Line(fstab_line, Display_Error, &twrp_flags)) + if (partition->Process_Fstab_Line(fstab_line, Display_Error, &twrp_flags, Sar_Detect)) Partitions.push_back(partition); else delete partition; @@ -213,7 +233,7 @@ int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error) for (std::map::iterator mapit=twrp_flags.begin(); mapit!=twrp_flags.end(); mapit++) { if (Find_Partition_By_Path(mapit->first) == NULL) { TWPartition* partition = new TWPartition(); - if (partition->Process_Fstab_Line(mapit->second.fstab_line, Display_Error, NULL)) + if (partition->Process_Fstab_Line(mapit->second.fstab_line, Display_Error, NULL, Sar_Detect)) Partitions.push_back(partition); else delete partition; @@ -227,6 +247,13 @@ int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error) std::vector::iterator iter; for (iter = Partitions.begin(); iter != Partitions.end(); iter++) { + if (Sar_Detect) { + if ((*iter)->Mount_Point == "/s") + return true; + else + continue; + } + (*iter)->Partition_Post_Processing(Display_Error); if ((*iter)->Is_Storage) { @@ -286,21 +313,29 @@ 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) { + Set_Crypto_State(); if (!Decrypt_Data->Key_Directory.empty() && Mount_By_Path(Decrypt_Data->Key_Directory, false)) { + Set_Crypto_Type("file"); #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)) { if (!Decrypt_Data->Decrypt_FBE_DE()) { - LOGINFO("Trying wrapped key.\n"); - property_set("fbe.data.wrappedkey", "true"); - if (!Decrypt_Data->Decrypt_FBE_DE()) { + char wrappedvalue[PROPERTY_VALUE_MAX]; + property_get("fbe.data.wrappedkey", wrappedvalue, ""); + std::string wrappedkeyvalue(wrappedvalue); + if (wrappedkeyvalue == "true") { LOGERR("Unable to decrypt FBE device\n"); + } else { + LOGINFO("Trying wrapped key.\n"); + property_set("fbe.data.wrappedkey", "true"); + if (!Decrypt_Data->Decrypt_FBE_DE()) { + LOGERR("Unable to decrypt FBE device\n"); + } } } @@ -324,6 +359,8 @@ int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error) } } } else { + Set_Crypto_State(); + Set_Crypto_Type("block"); int password_type = cryptfs_get_password_type(); if (password_type == CRYPT_TYPE_DEFAULT) { LOGINFO("Device is encrypted with the default password, attempting to decrypt.\n"); @@ -335,10 +372,12 @@ int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error) } } else { DataManager::SetValue("TW_CRYPTO_TYPE", password_type); + DataManager::SetValue("tw_crypto_pwtype_0", password_type); } } } - if (Decrypt_Data && (!Decrypt_Data->Is_Encrypted || Decrypt_Data->Is_Decrypted) && Decrypt_Data->Mount(false)) { + if (Decrypt_Data && (!Decrypt_Data->Is_Encrypted || Decrypt_Data->Is_Decrypted) && + Decrypt_Data->Mount(false)) { Decrypt_Adopted(); } #endif @@ -515,7 +554,7 @@ int TWPartitionManager::Mount_By_Path(string Path, bool Display_Error) { bool found = false; string Local_Path = TWFunc::Get_Root_Path(Path); - if (Local_Path == "/tmp" || Local_Path == "/") + if (Local_Path == "/tmp" || Local_Path == "/" || Local_Path == "/etc") return true; // Iterate through all partitions @@ -592,6 +631,8 @@ TWPartition* TWPartitionManager::Find_Partition_By_Path(const string& Path) { std::vector::iterator iter; string Local_Path = TWFunc::Get_Root_Path(Path); + if (Local_Path == "/system") + Local_Path = Get_Android_Root_Path(); for (iter = Partitions.begin(); iter != Partitions.end(); iter++) { if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path)) return (*iter); @@ -1099,6 +1140,10 @@ int TWPartitionManager::Run_Restore(const string& Restore_Name) { string Full_Filename = part_settings.Backup_Folder + "/" + part_settings.Part->Backup_FileName; + if (tw_get_default_metadata(Get_Android_Root_Path().c_str()) != 0) { + gui_msg(Msg(msg::kWarning, "restore_system_context=Unable to get default context for {1} -- Android may not boot.")(Get_Android_Root_Path())); + } + if (check_digest > 0 && !twrpDigestDriver::Check_Digest(Full_Filename)) return false; part_settings.partition_count++; @@ -1154,6 +1199,7 @@ int TWPartitionManager::Run_Restore(const string& Restore_Name) { } } TWFunc::GUI_Operation_Text(TW_UPDATE_SYSTEM_DETAILS_TEXT, gui_parse_text("{@updating_system_details}")); + tw_set_default_metadata(Get_Android_Root_Path().c_str()); UnMount_By_Path(Get_Android_Root_Path(), false); Update_System_Details(); UnMount_Main_Partitions(); @@ -1266,8 +1312,12 @@ void TWPartitionManager::Set_Restore_Files(string Restore_Name) { Part->Backup_FileName.resize(Part->Backup_FileName.size() - strlen(extn) + 3); } - if (!Part->Is_SubPartition) - Restore_List += Part->Backup_Path + ";"; + if (!Part->Is_SubPartition) { + if (Part->Backup_Path == Get_Android_Root_Path()) + Restore_List += "/system;"; + else + Restore_List += Part->Backup_Path + ";"; + } } closedir(d); } @@ -1285,13 +1335,24 @@ void TWPartitionManager::Set_Restore_Files(string Restore_Name) { int TWPartitionManager::Wipe_By_Path(string Path) { std::vector::iterator iter; + std::vector < TWPartition * >::iterator iter1; int ret = false; bool found = false; string Local_Path = TWFunc::Get_Root_Path(Path); + if (Local_Path == "/system") + Local_Path = Get_Android_Root_Path(); // Iterate through all partitions for (iter = Partitions.begin(); iter != Partitions.end(); iter++) { if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path)) { + // iterate through all partitions since some legacy devices uses other partitions as vendor causes issues while wiping + (*iter)->Find_Actual_Block_Device(); + for (iter1 = Partitions.begin (); iter1 != Partitions.end (); iter1++) + { + (*iter1)->Find_Actual_Block_Device(); + if ((*iter)->Actual_Block_Device == (*iter1)->Actual_Block_Device && (*iter)->Mount_Point != (*iter1)->Mount_Point) + (*iter1)->UnMount(false); + } if (Path == "/and-sec") ret = (*iter)->Wipe_AndSec(); else @@ -1368,10 +1429,10 @@ int TWPartitionManager::Wipe_Dalvik_Cache(void) { dir.push_back("/data/dalvik-cache"); - std::string cacheDir = TWFunc::get_cache_dir(); - if (cacheDir == NON_AB_CACHE_DIR) { - if (!PartitionManager.Mount_By_Path(NON_AB_CACHE_DIR, false)) { - LOGINFO("Unable to mount %s for wiping cache.\n", NON_AB_CACHE_DIR); + std::string cacheDir = TWFunc::get_log_dir(); + if (cacheDir == CACHE_LOGS_DIR) { + if (!PartitionManager.Mount_By_Path(CACHE_LOGS_DIR, false)) { + LOGINFO("Unable to mount %s for wiping cache.\n", CACHE_LOGS_DIR); } dir.push_back(cacheDir + "dalvik-cache"); dir.push_back(cacheDir + "/dc"); @@ -1386,7 +1447,7 @@ int TWPartitionManager::Wipe_Dalvik_Cache(void) { } } - if (cacheDir == NON_AB_CACHE_DIR) { + if (cacheDir == CACHE_LOGS_DIR) { gui_msg("wiping_cache_dalvik=Wiping Dalvik Cache Directories..."); } else { gui_msg("wiping_dalvik=Wiping Dalvik Directory..."); @@ -1398,7 +1459,7 @@ int TWPartitionManager::Wipe_Dalvik_Cache(void) { } } - if (cacheDir == NON_AB_CACHE_DIR) { + if (cacheDir == CACHE_LOGS_DIR) { gui_msg("cache_dalvik_done=-- Dalvik Cache Directories Wipe Complete!"); } else { gui_msg("dalvik_done=-- Dalvik Directory Wipe Complete!"); @@ -1456,9 +1517,6 @@ int TWPartitionManager::Format_Data(void) { TWPartition* dat = Find_Partition_By_Path("/data"); if (dat != NULL) { - if (!dat->UnMount(true)) - return false; - return dat->Wipe_Encryption(); } else { gui_msg(Msg(msg::kError, "unable_to_locate=Unable to locate {1}.")("/data")); @@ -1643,11 +1701,11 @@ void TWPartitionManager::Post_Decrypt(const string& Block_Device) { } else { gui_msg("decrypt_success_nodev=Data successfully decrypted"); } + property_set("twrp.decrypt.done", "true"); dat->Setup_File_System(false); - dat->Current_File_System = dat->Fstab_File_System; // Needed if we're ignoring blkid because encrypted devices start out as emmc + dat->Current_File_System = dat->Fstab_File_System; // Needed if we're ignoring blkid because encrypted devices start out as emmc - // Sleep for a bit so that the device will be ready - sleep(1); + sleep(1); // Sleep for a bit so that the device will be ready if (dat->Has_Data_Media && dat->Mount(false) && TWFunc::Path_Exists("/data/media/0")) { dat->Storage_Path = "/data/media/0"; dat->Symlink_Path = dat->Storage_Path; @@ -1655,6 +1713,7 @@ void TWPartitionManager::Post_Decrypt(const string& Block_Device) { DataManager::SetValue("tw_settings_path", "/data/media/0"); dat->UnMount(false); } + DataManager::LoadTWRPFolderInfo(); Update_System_Details(); Output_Partition(dat); UnMount_Main_Partitions(); @@ -1662,9 +1721,104 @@ void TWPartitionManager::Post_Decrypt(const string& Block_Device) { LOGERR("Unable to locate data partition.\n"); } -int TWPartitionManager::Decrypt_Device(string Password) { +void TWPartitionManager::Parse_Users() { +#ifdef TW_INCLUDE_FBE + char user_check_result[PROPERTY_VALUE_MAX]; + for (int userId = 0; userId <= 9999; userId++) { + string prop = "twrp.user." + to_string(userId) + ".decrypt"; + property_get(prop.c_str(), user_check_result, "-1"); + if (strcmp(user_check_result, "-1") != 0) { + if (userId < 0 || userId > 9999) { + LOGINFO("Incorrect user id %d\n", userId); + continue; + } + struct users_struct user; + user.userId = to_string(userId); + + // Attempt to get name of user. Fallback to user ID if this fails. + std::string path = "/data/system/users/" + to_string(userId) + ".xml"; + if ((atoi(TWFunc::System_Property_Get("ro.build.version.sdk").c_str()) > 30) && TWFunc::Path_Exists(path)) { + if(!TWFunc::Check_Xml_Format(path.c_str())) + user.userName = to_string(userId); + } + else { + char* userFile = PageManager::LoadFileToBuffer(path, NULL); + if (userFile == NULL) { + user.userName = to_string(userId); + } + else { + xml_document<> *userXml = new xml_document<>(); + userXml->parse<0>(userFile); + xml_node<>* userNode = userXml->first_node("user"); + if (userNode == nullptr) { + user.userName = to_string(userId); + } else { + xml_node<>* nameNode = userNode->first_node("name"); + if (nameNode == nullptr) + user.userName = to_string(userId); + else { + string userName = nameNode->value(); + user.userName = userName + " (" + to_string(userId) + ")"; + } + } + } + } + + string filename; + user.type = Get_Password_Type(userId, filename); + + user.isDecrypted = false; + if (strcmp(user_check_result, "1") == 0) + user.isDecrypted = true; + Users_List.push_back(user); + } + } + Check_Users_Decryption_Status(); +#endif +} + +std::vector* TWPartitionManager::Get_Users_List() { + return &Users_List; +} + +void TWPartitionManager::Mark_User_Decrypted(int userID) { +#ifdef TW_INCLUDE_FBE + std::vector::iterator iter; + for (iter = Users_List.begin(); iter != Users_List.end(); iter++) { + if (atoi((*iter).userId.c_str()) == userID) { + (*iter).isDecrypted = true; + string user_prop_decrypted = "twrp.user." + to_string(userID) + ".decrypt"; + property_set(user_prop_decrypted.c_str(), "1"); + break; + } + } + Check_Users_Decryption_Status(); +#endif +} + +void TWPartitionManager::Check_Users_Decryption_Status() { +#ifdef TW_INCLUDE_FBE + int all_is_decrypted = 1; + std::vector::iterator iter; + for (iter = Users_List.begin(); iter != Users_List.end(); iter++) { + if (!(*iter).isDecrypted) { + LOGINFO("User %s is not decrypted.\n", (*iter).userId.c_str()); + all_is_decrypted = 0; + break; + } + } + if (all_is_decrypted == 1) { + LOGINFO("All found users are decrypted.\n"); + DataManager::SetValue("tw_all_users_decrypted", "1"); + property_set("twrp.all.users.decrypted", "true"); + } else + DataManager::SetValue("tw_all_users_decrypted", "0"); +#endif +} + +int TWPartitionManager::Decrypt_Device(string Password, int user_id) { #ifdef TW_INCLUDE_CRYPTO - char crypto_state[PROPERTY_VALUE_MAX], crypto_blkdev[PROPERTY_VALUE_MAX]; + char crypto_blkdev[PROPERTY_VALUE_MAX]; std::vector::iterator iter; // Mount any partitions that need to be mounted for decrypt @@ -1675,25 +1829,56 @@ int TWPartitionManager::Decrypt_Device(string Password) { } property_set("twrp.mount_to_decrypt", "1"); - property_get("ro.crypto.state", crypto_state, "error"); - if (strcmp(crypto_state, "error") == 0) { - property_set("ro.crypto.state", "encrypted"); - // Sleep for a bit so that services can start if needed - sleep(1); - } + Set_Crypto_State(); + Set_Crypto_Type("block"); if (DataManager::GetIntValue(TW_IS_FBE)) { #ifdef TW_INCLUDE_FBE if (!Mount_By_Path("/data", true)) // /data has to be mounted for FBE return -1; + + bool user_need_decrypt = false; + std::vector::iterator iter; + for (iter = Users_List.begin(); iter != Users_List.end(); iter++) { + if (atoi((*iter).userId.c_str()) == user_id && !(*iter).isDecrypted) { + user_need_decrypt = true; + } + } + if (!user_need_decrypt) { + LOGINFO("User %d does not require decryption\n", user_id); + return 0; + } + int retry_count = 10; while (!TWFunc::Path_Exists("/data/system/users/gatekeeper.password.key") && --retry_count) - usleep(2000); // A small sleep is needed after mounting /data to ensure reliable decrypt... maybe because of DE? - int user_id = DataManager::GetIntValue("tw_decrypt_user_id"); - LOGINFO("Decrypting FBE for user %i\n", user_id); + usleep(2000); // A small sleep is needed after mounting /data to ensure reliable decrypt...maybe because of DE? + gui_msg(Msg("decrypting_user_fbe=Attempting to decrypt FBE for user {1}...")(user_id)); if (Decrypt_User(user_id, Password)) { - Post_Decrypt(""); + gui_msg(Msg("decrypt_user_success_fbe=User {1} Decrypted Successfully")(user_id)); + Mark_User_Decrypted(user_id); + if (user_id == 0) { + // When decrypting user 0 also try all other users + std::vector::iterator iter; + for (iter = Users_List.begin(); iter != Users_List.end(); iter++) { + if ((*iter).userId == "0" || (*iter).isDecrypted) + continue; + + int tmp_user_id = atoi((*iter).userId.c_str()); + gui_msg(Msg("decrypting_user_fbe=Attempting to decrypt FBE for user {1}...")(tmp_user_id)); + if (Decrypt_User(tmp_user_id, Password) || + (Password != "!" && Decrypt_User(tmp_user_id, "!"))) { // "!" means default password + gui_msg(Msg("decrypt_user_success_fbe=User {1} Decrypted Successfully")(tmp_user_id)); + Mark_User_Decrypted(tmp_user_id); + } else { + gui_msg(Msg("decrypt_user_fail_fbe=Failed to decrypt user {1}")(tmp_user_id)); + } + } + Post_Decrypt(""); + } + return 0; + } else { + gui_msg(Msg(msg::kError, "decrypt_user_fail_fbe=Failed to decrypt user {1}")(user_id)); } #else LOGERR("FBE support is not present\n"); @@ -1701,6 +1886,13 @@ int TWPartitionManager::Decrypt_Device(string Password) { return -1; } + char isdecrypteddata[PROPERTY_VALUE_MAX]; + property_get("twrp.decrypt.done", isdecrypteddata, ""); + if (strcmp(isdecrypteddata, "true") == 0) { + LOGINFO("Data has no decryption required\n"); + return 0; + } + int pwret = -1; pid_t pid = fork(); if (pid < 0) { @@ -1864,8 +2056,12 @@ int TWPartitionManager::usb_storage_enable(void) { Mount2 = Find_Next_Storage(Mount1->Mount_Point, true); if (Mount2 && Mount2->Mount_Point != Mount1->Mount_Point) { Open_Lun_File(Mount2->Mount_Point, lun_file); + // Mimic single lun code: Mount CurrentStoragePath if it's not /data + } else if (TWFunc::Get_Root_Path(DataManager::GetCurrentStoragePath()) != "/data") { + Open_Lun_File(DataManager::GetCurrentStoragePath(), lun_file); } - } else { + // Mimic single lun code: Mount CurrentStoragePath if it's not /data + } else if (TWFunc::Get_Root_Path(DataManager::GetCurrentStoragePath()) != "/data" && !Open_Lun_File(DataManager::GetCurrentStoragePath(), lun_file)) { gui_err("unable_locate_storage=Unable to locate storage device."); goto error_handle; } @@ -2250,14 +2446,14 @@ void TWPartitionManager::Output_Storage_Fstab(void) { std::vector::iterator iter; char storage_partition[255]; std::string Temp; - std::string cacheDir = TWFunc::get_cache_dir(); + std::string cacheDir = TWFunc::get_log_dir(); if (cacheDir.empty()) { LOGINFO("Unable to find cache directory\n"); return; } - std::string storageFstab = TWFunc::get_cache_dir() + "recovery/storage.fstab"; + std::string storageFstab = TWFunc::get_log_dir() + "recovery/storage.fstab"; FILE *fp = fopen(storageFstab.c_str(), "w"); if (fp == NULL) { @@ -2519,11 +2715,17 @@ bool TWPartitionManager::Remove_MTP_Storage(unsigned int Storage_ID) { } bool TWPartitionManager::Flash_Image(string& path, string& filename) { + twrpRepacker repacker; int partition_count = 0; TWPartition* flash_part = NULL; string Flash_List, flash_path, full_filename; size_t start_pos = 0, end_pos = 0; +#ifdef TW_AMONET + if (load_microloader() < 0) + return false; +#endif + full_filename = path + "/" + filename; gui_msg("image_flash_start=[IMAGE FLASH STARTED]"); @@ -2552,7 +2754,7 @@ bool TWPartitionManager::Flash_Image(string& path, string& filename) { Repack_Options.Disable_Verity = false; Repack_Options.Disable_Force_Encrypt = false; Repack_Options.Backup_First = DataManager::GetIntValue("tw_repack_backup_first") != 0; - return Repack_Images(full_filename, Repack_Options); + return repacker.Repack_Image_And_Flash(full_filename, Repack_Options); } PartitionSettings part_settings; part_settings.Backup_Folder = path; @@ -2597,6 +2799,12 @@ bool TWPartitionManager::Flash_Image(string& path, string& filename) { return false; } gui_highlight("flash_done=IMAGE FLASH COMPLETED]"); +#ifdef TW_AMONET + if (patch_part("/boot") < 0) + return false; + if (patch_part("/recovery") < 0) + return false; +#endif return true; } @@ -2692,6 +2900,16 @@ bool TWPartitionManager::Decrypt_Adopted() { LOGERR("Cannot decrypt adopted storage because /data will not mount\n"); return false; } + + // In Android 12 xml format changed. Previously it was human-readable format with xml tags + // now it's ABX (Android Binary Xml). Sadly, rapidxml can't parse it, so check xml format firstly + std::string path = "/data/system/storage.xml"; + if ((atoi(TWFunc::System_Property_Get("ro.build.version.sdk").c_str()) > 30) && TWFunc::Path_Exists(path)) + if(!TWFunc::Check_Xml_Format(path.c_str())) { + LOGINFO("Android 12+: storage.xml is in ABX format. Skipping adopted storage decryption\n"); + return false; + } + LOGINFO("Decrypt adopted storage starting\n"); char* xmlFile = PageManager::LoadFileToBuffer("/data/system/storage.xml", NULL); xml_document<> *doc = NULL; @@ -2714,6 +2932,16 @@ bool TWPartitionManager::Decrypt_Adopted() { } std::vector::iterator adopt; for (adopt = Partitions.begin(); adopt != Partitions.end(); adopt++) { + if ((*adopt)->Removable && !(*adopt)->Is_Present && (*adopt)->Adopted_Mount_Delay > 0) { + // On some devices, the external mmc driver takes some time + // to recognize the card, in which case the "actual block device" + // would not have been found yet. We wait the specified delay + // and then try again. + LOGINFO("Sleeping %d seconds for adopted storage.\n", (*adopt)->Adopted_Mount_Delay); + sleep((*adopt)->Adopted_Mount_Delay); + (*adopt)->Find_Actual_Block_Device(); + } + if ((*adopt)->Removable && (*adopt)->Is_Present) { if ((*adopt)->Decrypt_Adopted() == 0) { ret = true; @@ -2787,6 +3015,13 @@ void TWPartitionManager::Remove_Partition_By_Path(string Path) { } } +void TWPartitionManager::Override_Active_Slot(const string& Slot) { + LOGINFO("Overriding slot to '%s'\n", Slot.c_str()); + Active_Slot_Display = Slot; + DataManager::SetValue("tw_active_slot", Slot); + PartitionManager.Update_System_Details(); +} + void TWPartitionManager::Set_Active_Slot(const string& Slot) { if (Slot != "A" && Slot != "B") { LOGERR("Set_Active_Slot invalid slot '%s'\n", Slot.c_str()); @@ -2831,10 +3066,9 @@ string TWPartitionManager::Get_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; + if (property_get_bool("ro.twrp.sar", false)) + return "/system_root"; + return "/system"; } void TWPartitionManager::Remove_Uevent_Devices(const string& Mount_Point) { @@ -2960,7 +3194,7 @@ void TWPartitionManager::read_uevent() { int len = recv(uevent_pfd.fd, buf, sizeof(buf), MSG_DONTWAIT); if (len == -1) { - LOGERR("recv error on uevent\n"); + LOGINFO("recv error on uevent\n"); return; } /*int i = 0; // Print all uevent output for test /debug @@ -3041,159 +3275,3 @@ bool TWPartitionManager::Prepare_Empty_Folder(const std::string& Folder) { TWFunc::removeDir(Folder, false); return TWFunc::Recursive_Mkdir(Folder); } - -bool TWPartitionManager::Prepare_Repack(TWPartition* Part, const std::string& Temp_Folder_Destination, const bool Create_Backup, const std::string& Backup_Name) { - if (!Part) { - LOGERR("Partition was null!\n"); - return false; - } - if (!Prepare_Empty_Folder(Temp_Folder_Destination)) - return false; - std::string target_image = Temp_Folder_Destination + "boot.img"; - PartitionSettings part_settings; - part_settings.Part = Part; - if (Create_Backup) { - if (Check_Backup_Name(Backup_Name, true, false) != 0) - return false; - DataManager::GetValue(TW_BACKUPS_FOLDER_VAR, part_settings.Backup_Folder); - part_settings.Backup_Folder = part_settings.Backup_Folder + "/" + TWFunc::Get_Current_Date() + " " + Backup_Name + "/"; - if (!TWFunc::Recursive_Mkdir(part_settings.Backup_Folder)) - return false; - } else - part_settings.Backup_Folder = Temp_Folder_Destination; - part_settings.adbbackup = false; - part_settings.generate_digest = false; - part_settings.generate_md5 = false; - part_settings.PM_Method = PM_BACKUP; - part_settings.progress = NULL; - pid_t not_a_pid = 0; - if (!Part->Backup(&part_settings, ¬_a_pid)) - return false; - std::string backed_up_image = part_settings.Backup_Folder; - backed_up_image += Part->Backup_FileName; - target_image = Temp_Folder_Destination + "boot.img"; - if (Create_Backup) { - std::string source = part_settings.Backup_Folder + Part->Backup_FileName; - if (TWFunc::copy_file(source, target_image, 0644) != 0) { - LOGERR("Failed to copy backup file '%s' to temp folder target '%s'\n", source.c_str(), target_image.c_str()); - return false; - } - } else { - if (rename(backed_up_image.c_str(), target_image.c_str()) != 0) { - LOGERR("Failed to rename '%s' to '%s'\n", backed_up_image.c_str(), target_image.c_str()); - return false; - } - } - return Prepare_Repack(target_image, Temp_Folder_Destination, false, false); -} - -bool TWPartitionManager::Prepare_Repack(const std::string& Source_Path, const std::string& Temp_Folder_Destination, const bool Copy_Source, const bool Create_Destination) { - if (Create_Destination) { - if (!Prepare_Empty_Folder(Temp_Folder_Destination)) - return false; - } - if (Copy_Source) { - std::string destination = Temp_Folder_Destination + "/boot.img"; - if (TWFunc::copy_file(Source_Path, destination, 0644)) - return false; - } - std::string command = "cd " + Temp_Folder_Destination + " && /sbin/magiskboot --unpack -h '" + Source_Path +"'"; - if (TWFunc::Exec_Cmd(command) != 0) { - LOGINFO("Error unpacking %s!\n", Source_Path.c_str()); - gui_msg(Msg(msg::kError, "unpack_error=Error unpacking image.")); - return false; - } - return true; -} - -bool TWPartitionManager::Repack_Images(const std::string& Target_Image, const struct Repack_Options_struct& Repack_Options) { - if (!TWFunc::Path_Exists("/sbin/magiskboot")) { - LOGERR("Image repacking tool not present in this TWRP build!"); - return false; - } - DataManager::SetProgress(0); - TWPartition* part = PartitionManager.Find_Partition_By_Path("/boot"); - if (part) - gui_msg(Msg("unpacking_image=Unpacking {1}...")(part->Display_Name)); - else { - gui_msg(Msg(msg::kError, "unable_to_locate=Unable to locate {1}.")("/boot")); - return false; - } - if (!PartitionManager.Prepare_Repack(part, REPACK_ORIG_DIR, Repack_Options.Backup_First, gui_lookup("repack", "Repack"))) - return false; - DataManager::SetProgress(.25); - gui_msg(Msg("unpacking_image=Unpacking {1}...")(Target_Image)); - if (!PartitionManager.Prepare_Repack(Target_Image, REPACK_NEW_DIR, true)) - return false; - DataManager::SetProgress(.5); - gui_msg(Msg("repacking_image=Repacking {1}...")(part->Display_Name)); - std::string path = REPACK_NEW_DIR; - if (Repack_Options.Type == REPLACE_KERNEL) { - // When we replace the kernel, what we really do is copy the boot partition ramdisk into the new image's folder - if (TWFunc::copy_file(REPACK_ORIG_DIR "ramdisk.cpio", REPACK_NEW_DIR "ramdisk.cpio", 0644)) { - LOGERR("Failed to copy ramdisk\n"); - return false; - } - } else if (Repack_Options.Type == REPLACE_RAMDISK) { - // Repack the ramdisk - if (TWFunc::copy_file(REPACK_NEW_DIR "ramdisk.cpio", REPACK_ORIG_DIR "ramdisk.cpio", 0644)) { - LOGERR("Failed to copy ramdisk\n"); - return false; - } - path = REPACK_ORIG_DIR; - } else { - LOGERR("Invalid repacking options specified\n"); - return false; - } - if (Repack_Options.Disable_Verity) - LOGERR("Disabling verity is not implemented yet\n"); - if (Repack_Options.Disable_Force_Encrypt) - LOGERR("Disabling force encrypt is not implemented yet\n"); - std::string command = "cd " + path + " && /sbin/magiskboot --repack " + path + "boot.img"; - if (TWFunc::Exec_Cmd(command) != 0) { - gui_msg(Msg(msg::kError, "repack_error=Error repacking image.")); - return false; - } - DataManager::SetProgress(.75); - std::string file = "new-boot.img"; - DataManager::SetValue("tw_flash_partition", "/boot;"); - if (!PartitionManager.Flash_Image(path, file)) { - LOGINFO("Error flashing new image\n"); - return false; - } - DataManager::SetProgress(1); - TWFunc::removeDir(REPACK_ORIG_DIR, false); - if (part->SlotSelect && Repack_Options.Type == REPLACE_RAMDISK) { - LOGINFO("Switching slots to flash ramdisk to both partitions\n"); - string Current_Slot = Get_Active_Slot_Display(); - if (Current_Slot == "A") - Set_Active_Slot("B"); - else - Set_Active_Slot("A"); - DataManager::SetProgress(.25); - if (!PartitionManager.Prepare_Repack(part, REPACK_ORIG_DIR, Repack_Options.Backup_First, gui_lookup("repack", "Repack"))) - return false; - if (TWFunc::copy_file(REPACK_NEW_DIR "ramdisk.cpio", REPACK_ORIG_DIR "ramdisk.cpio", 0644)) { - LOGERR("Failed to copy ramdisk\n"); - return false; - } - path = REPACK_ORIG_DIR; - command = "cd " + path + " && /sbin/magiskboot --repack " + path + "boot.img"; - if (TWFunc::Exec_Cmd(command) != 0) { - gui_msg(Msg(msg::kError, "repack_error=Error repacking image.")); - return false; - } - DataManager::SetProgress(.75); - std::string file = "new-boot.img"; - DataManager::SetValue("tw_flash_partition", "/boot;"); - if (!PartitionManager.Flash_Image(path, file)) { - LOGINFO("Error flashing new image\n"); - return false; - } - DataManager::SetProgress(1); - TWFunc::removeDir(REPACK_ORIG_DIR, false); - Set_Active_Slot(Current_Slot); - } - TWFunc::removeDir(REPACK_NEW_DIR, false); - return true; -} diff --git a/partitions.hpp b/partitions.hpp old mode 100644 new mode 100755 index 4071b942c0..58fcd818c5 --- a/partitions.hpp +++ b/partitions.hpp @@ -27,6 +27,10 @@ #include "tw_atomic.hpp" #include "progresstracking.hpp" +#ifdef USE_EXT4 +#include "ext4crypt_tar.h" +#endif + #define MAX_FSTAB_LINE_LENGTH 2048 #define REPACK_ORIG_DIR "/tmp/repackorig/" @@ -75,19 +79,6 @@ struct Flags_Map { char* fstab_line; }; -enum Repack_Type { - REPLACE_NONE = 0, - REPLACE_RAMDISK = 1, - REPLACE_KERNEL = 2, -}; - -struct Repack_Options_struct { - Repack_Type Type; - bool Backup_First; - bool Disable_Verity; - bool Disable_Force_Encrypt; -}; - enum PartitionManager_Op { // PartitionManager Restore Mode for Raw_Read_Write() PM_BACKUP = 0, PM_RESTORE = 1, @@ -159,9 +150,12 @@ class TWPartition int Decrypt_Adopted(); void Revert_Adopted(); 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 + void Set_Backup_FileName(string fname); // Set backup filename for partition + std::string Get_Backup_FileName(); // Get the backup filename for the 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 + std::string Get_Display_Name(); // Get the display name in the gui for the partition + bool Is_SlotSelect(); // Return whether the partition is a slot partition or not public: string Current_File_System; // Current file system @@ -172,13 +166,14 @@ class TWPartition string Crypto_Key_Location; // Location of the crypto key used for decrypting encrypted data partitions unsigned int MTP_Storage_ID; string Adopted_GUID; + unsigned int Adopted_Mount_Delay; protected: bool Has_Data_Media; // Indicates presence of /data/media, may affect wiping and backup methods void Setup_Data_Media(); // Sets up a partition as a /data/media emulated storage partition private: - bool Process_Fstab_Line(const char *fstab_line, bool Display_Error, std::map *twrp_flags); // Processes a fstab line + bool Process_Fstab_Line(const char *fstab_line, bool Display_Error, std::map *twrp_flags, bool Sar_Detect); // Processes a fstab line void Setup_Data_Partition(bool Display_Error); // Setup data partition after fstab processed void Setup_Cache_Partition(bool Display_Error); // Setup cache partition after fstab processed bool Find_Wildcard_Block_Devices(const string& Device); // Searches for and finds wildcard block devices @@ -207,6 +202,7 @@ class TWPartition bool Wipe_NTFS(); // Uses mkntfs to wipe bool Wipe_Data_Without_Wiping_Media(); // Uses rm -rf to wipe but does not wipe /data/media bool Wipe_Data_Without_Wiping_Media_Func(const string& parent); // Uses rm -rf to wipe but does not wipe /data/media + bool Recreate_Logs_Dir(); // Recreate TWRP_AB_LOGS_DIR after wipe void Wipe_Crypto_Key(); // Wipe crypto key from either footer or block device bool Backup_Tar(PartitionSettings *part_settings, pid_t *tar_fork_pid); // Backs up using tar for file systems bool Backup_Image(PartitionSettings *part_settings); // Backs up using raw read/write for emmc memory types @@ -281,7 +277,9 @@ class TWPartition 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 + string Key_Directory; // Metadata key directory needed for mounting FBE encrypted data partitions using metadata encryption + string Original_Path; + bool Use_Original_Path; 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; @@ -298,6 +296,13 @@ friend class GUIAction; friend class PageManager; }; +struct users_struct { + std::string userId; + std::string userName; + int type; + bool isDecrypted; +}; + class TWPartitionManager { public: @@ -305,7 +310,7 @@ class TWPartitionManager ~TWPartitionManager() {} public: - int Process_Fstab(string Fstab_Filename, bool Display_Error); // Parses the fstab and populates the partitions + int Process_Fstab(string Fstab_Filename, bool Display_Error, bool Sar_Detect); // Parses the fstab and populates the partitions int Write_Fstab(); // Creates /etc/fstab file that's used by the command line for mount commands void Output_Partition_Logging(); // Outputs partition information to the log void Output_Partition(TWPartition* Part); // Outputs partition details to the log @@ -334,7 +339,8 @@ class TWPartitionManager int Repair_By_Path(string Path, bool Display_Error); // Repairs a partition based on path int Resize_By_Path(string Path, bool Display_Error); // Resizes a partition based on path void Update_System_Details(); // Updates fstab, file systems, sizes, etc. - int Decrypt_Device(string Password); // Attempt to decrypt any encrypted partitions + int Decrypt_Device(string Password, int user_id = 0); // Attempt to decrypt any encrypted partitions + void Parse_Users(); // Parse FBE users int usb_storage_enable(void); // Enable USB storage mode int usb_storage_disable(void); // Disable USB storage mode void Mount_All_Storage(void); // Mounts all storage locations @@ -365,6 +371,7 @@ class TWPartitionManager bool Flash_Image(string& path, string& filename); // Flashes an image to a selected partition from the partition list bool Restore_Partition(struct PartitionSettings *part_settings); // Restore the partitions based on type TWAtomicInt stop_backup; + void Override_Active_Slot(const string& Slot); // Override the active slot for repacking 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 @@ -377,9 +384,9 @@ class TWPartitionManager void read_uevent(); // Reads uevent data into a buffer void close_uevent(); // Closes the uevent netlink socket void Add_Partition(TWPartition* Part); // Adds a new partition to the Partitions vector - bool Prepare_Repack(TWPartition* Part, const std::string& Temp_Folder_Destination, const bool Create_Backup, const std::string& Backup_Name); // Prepares an image for repacking by unpacking it to the temp folder destination - bool Prepare_Repack(const std::string& Source_Path, const std::string& Temp_Folder_Destination, const bool Copy_Source, const bool Create_Destination = true); // Prepares an image for repacking by unpacking it to the temp folder destination - bool Repack_Images(const std::string& Target_Image, const struct Repack_Options_struct& Repack_Options); // Repacks the boot image with a new kernel or a new ramdisk + std::vector* Get_Users_List(); // Returns pointer to list of users + void Set_Crypto_State(); // Sets encryption state for devices (ro.crypto.state) + int Set_Crypto_Type(const char* crypto_type); // Sets encryption type for FDE (block) and FBE (file) devices (ro.crypto.type) private: void Setup_Settings_Storage_Partition(TWPartition* Part); // Sets up settings storage @@ -398,10 +405,15 @@ class TWPartitionManager int mtp_write_fd; pid_t tar_fork_pid; // PID of twrpTar fork Backup_Method_enum Backup_Method; // Method used for backup + void Mark_User_Decrypted(int userID); // Marks given user ID in Users_List as decrypted + void Check_Users_Decryption_Status(); // Checks to see if all users are decrypted + std::string original_ramdisk_format; // Ramdisk format of boot partition + std::string repacked_ramdisk_format; // Ramdisk format of boot image to repack from private: std::vector Partitions; // Vector list of all partitions string Active_Slot_Display; // Current Active Slot (A or B) for display purposes + std::vector Users_List; // List of FBE users }; extern TWPartitionManager PartitionManager; diff --git a/prebuilt/Android.mk b/prebuilt/Android.mk index d330799942..17636ae654 100644 --- a/prebuilt/Android.mk +++ b/prebuilt/Android.mk @@ -30,9 +30,6 @@ else ifeq ($(shell test $(PLATFORM_SDK_VERSION) -gt 23; echo $$?),0) RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/dd endif - 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 @@ -59,6 +56,9 @@ RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/mke2fs RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/tune2fs RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/resize2fs RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/simg2img +ifneq ($(TW_OZIP_DECRYPT_KEY),) + RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/ozip_decrypt +endif ifneq ($(TARGET_ARCH), x86_64) RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/linker endif @@ -226,6 +226,12 @@ ifeq ($(TW_INCLUDE_CRYPTO), true) RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/keystore_cli RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/servicemanager RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.system.wifi.keystore@1.0.so + ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 28; echo $$?),0) + RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.vibrator@1.0.so + RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.vibrator@1.1.so + RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.vibrator@1.2.so + endif + ifneq ($(wildcard system/keymaster/keymaster_stl.cpp),) RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeymaster_portable.so RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeymaster_staging.so @@ -399,6 +405,16 @@ ifeq ($(shell test $(PLATFORM_SDK_VERSION) -gt 27; echo $$?),0) RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/liblogwrap.so RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext2_misc.so endif +ifneq ($(TW_EXCLUDE_NANO), true) + RELINK_SOURCE_FILES += $(TARGET_OUT_OPTIONAL_EXECUTABLES)/nano + RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libncurses.so + RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libssh.so + RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libssl.so +endif +ifneq ($(TW_EXCLUDE_BASH), true) + RELINK_SOURCE_FILES += $(TARGET_OUT_OPTIONAL_EXECUTABLES)/bash + RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libncurses.so +endif TW_BB_SYMLINKS := ifneq ($(TW_USE_TOOLBOX), true) @@ -562,6 +578,15 @@ LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin LOCAL_SRC_FILES := $(LOCAL_MODULE) include $(BUILD_PREBUILT) +#TWRP App permissions for Android 9+ +include $(CLEAR_VARS) +LOCAL_MODULE := privapp-permissions-twrpapp.xml +LOCAL_MODULE_TAGS := eng +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) @@ -577,11 +602,65 @@ ifeq ($(TW_INCLUDE_CRYPTO), true) endif endif -ifeq ($(TW_INCLUDE_REPACKTOOLS), true) +ifneq (,$(filter $(TW_INCLUDE_REPACKTOOLS) $(TW_INCLUDE_RESETPROP) $(TW_INCLUDE_LIBRESETPROP), true)) ifeq ($(wildcard external/magisk-prebuilt/Android.mk),) - $(warning Magisk repacking tools not found!) + $(warning Magisk prebuilt tools not found!) $(warning Please place https://github.com/TeamWin/external_magisk-prebuilt) $(warning into external/magisk-prebuilt) $(error magiskboot prebuilts not present; exiting) endif endif + +# Include tzdata in TWRP to fix "__bionic_open_tzdata" log spam +# Dummy file to apply post-install patch +ifneq ($(TW_EXCLUDE_TZDATA), true) + include $(CLEAR_VARS) + LOCAL_MODULE := tzdata_twrp + LOCAL_MODULE_TAGS := optional + LOCAL_MODULE_CLASS := ETC + LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/sbin + LOCAL_REQUIRED_MODULES := tzdata + + ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true) + LOCAL_POST_INSTALL_CMD += \ + rm -f $(TARGET_RECOVERY_ROOT_OUT)/system_root/system/usr/share/zoneinfo/tzdata; \ + mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/system_root/system/usr/share/zoneinfo; \ + cp -f $(TARGET_OUT)/usr/share/zoneinfo/tzdata $(TARGET_RECOVERY_ROOT_OUT)/system_root/system/usr/share/zoneinfo/; + else + LOCAL_POST_INSTALL_CMD += \ + rm -f $(TARGET_RECOVERY_ROOT_OUT)/system/usr/share/zoneinfo/tzdata; \ + mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/system/usr/share/zoneinfo; \ + cp -f $(TARGET_OUT)/usr/share/zoneinfo/tzdata $(TARGET_RECOVERY_ROOT_OUT)/system/usr/share/zoneinfo/; + endif + include $(BUILD_PHONY_PACKAGE) +endif + +include $(CLEAR_VARS) +LOCAL_MODULE := nano_twrp +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/sbin +LOCAL_REQUIRED_MODULES := nano libncurses +LOCAL_POST_INSTALL_CMD += \ + mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/sbin/etc/nano; \ + cp -rf external/nano/etc/* external/nano/syntax/*.nanorc $(TARGET_RECOVERY_ROOT_OUT)/sbin/etc/nano/; \ + cp -rf external/libncurses/lib/terminfo $(TARGET_RECOVERY_ROOT_OUT)/sbin/etc/; +include $(BUILD_PHONY_PACKAGE) + +ifneq ($(TW_EXCLUDE_BASH), true) + include $(CLEAR_VARS) + LOCAL_MODULE := bash_twrp + LOCAL_MODULE_TAGS := optional + LOCAL_MODULE_CLASS := ETC + LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/sbin + LOCAL_REQUIRED_MODULES := bash + +LOCAL_POST_INSTALL_CMD += \ + mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/sbin/etc/bash; \ + cp -rf external/bash/etc/* $(TARGET_RECOVERY_ROOT_OUT)/sbin/etc/bash/; \ + sed -i 's/ro.cm.device/ro.product.device/' $(TARGET_RECOVERY_ROOT_OUT)/sbin/etc/bash/bashrc; \ + sed -i 's/ro.lineage.device/ro.product.device/' $(TARGET_RECOVERY_ROOT_OUT)/sbin/etc/bash/bashrc; \ + sed -i 's/ro.omni.device/ro.product.device/' $(TARGET_RECOVERY_ROOT_OUT)/sbin/etc/bash/bashrc; \ + sed -i '/export TERM/d' $(TARGET_RECOVERY_ROOT_OUT)/sbin/etc/bash/bashrc; + include $(BUILD_PHONY_PACKAGE) +endif diff --git a/prebuilt/privapp-permissions-twrpapp.xml b/prebuilt/privapp-permissions-twrpapp.xml new file mode 100644 index 0000000000..9b294c2917 --- /dev/null +++ b/prebuilt/privapp-permissions-twrpapp.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/scripts/language_helper.py b/scripts/language_helper.py index 9fa956b2d1..67bd20120c 100644 --- a/scripts/language_helper.py +++ b/scripts/language_helper.py @@ -129,7 +129,7 @@ def toprettyxml(xdoc, encoding): break if found == False: print "'%s' present in English and not in %s" % (child.attributes['name'].value.encode("utf-8"), otherlang) - notfound_err = "NOT FOUND " + child.toxml() + notfound_err = "NOT FOUND " + child.toxml().replace('--', '\-\-') notfound_comment = doc.createComment(notfound_err) resources.appendChild(notfound_comment) elif child.nodeType == child.COMMENT_NODE: diff --git a/twinstall.cpp b/twinstall.cpp index d659b47b10..f7af933f58 100755 --- a/twinstall.cpp +++ b/twinstall.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,8 @@ #include "legacy_property_service.h" #include "twinstall.h" #include "installcommand.h" +#include "twrpRepacker.hpp" +#include "amonet.h" extern "C" { #include "gui/gui.h" } @@ -299,7 +302,7 @@ static int Run_Update_Binary(const char *path, ZipWrap *Zip, int* wipe_cache, zi } else if (strcmp(command, "set_progress") == 0) { char* fraction_char = strtok(NULL, " \n"); float fraction_float = strtof(fraction_char, NULL); - DataManager::SetProgress(fraction_float); + DataManager::_SetProgress(fraction_float); } else if (strcmp(command, "ui_print") == 0) { char* display_value = strtok(NULL, "\n"); if (display_value) { @@ -338,8 +341,8 @@ static int Run_Update_Binary(const char *path, ZipWrap *Zip, int* wipe_cache, zi return INSTALL_SUCCESS; } -int TWinstall_zip(const char* path, int* wipe_cache) { - int ret_val, zip_verify = 1; +int TWinstall_zip(const char* path, int* wipe_cache, bool check_for_digest) { + int ret_val, zip_verify = 1, unmount_system = 1, reflashtwrp = 0; if (strcmp(path, "error") == 0) { LOGERR("Failed to get adb sideload file: '%s'\n", path); @@ -351,14 +354,18 @@ int TWinstall_zip(const char* path, int* wipe_cache) { string digest_str; string Full_Filename = path; - gui_msg("check_for_digest=Checking for Digest file..."); + if (check_for_digest) { + gui_msg("check_for_digest=Checking for Digest file..."); - if (*path != '@' && !twrpDigestDriver::Check_File_Digest(Full_Filename)) { - LOGERR("Aborting zip install: Digest verification failed\n"); - return INSTALL_CORRUPT; + if (*path != '@' && !twrpDigestDriver::Check_File_Digest(Full_Filename)) { + LOGERR("Aborting zip install: Digest verification failed\n"); + return INSTALL_CORRUPT; + } } } + DataManager::GetValue(TW_UNMOUNT_SYSTEM, unmount_system); + #ifndef TW_OEM_BUILD DataManager::GetValue(TW_SIGNED_ZIP_VERIFY_VAR, zip_verify); #endif @@ -410,6 +417,16 @@ int TWinstall_zip(const char* path, int* wipe_cache) { return INSTALL_CORRUPT; } + if (unmount_system) { + gui_msg("unmount_system=Unmounting System..."); + if(!PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) { + gui_err("unmount_system_err=Failed unmounting System"); + return -1; + } + unlink("/system"); + mkdir("/system", 0755); + } + time_t start, stop; time(&start); if (Zip.EntryExists(ASSUMED_UPDATE_BINARY_NAME)) { @@ -424,13 +441,47 @@ int TWinstall_zip(const char* path, int* wipe_cache) { ret_val = INSTALL_CORRUPT; } else { ret_val = Prepare_Update_Binary(path, &Zip, wipe_cache); - if (ret_val == INSTALL_SUCCESS) - ret_val = Run_Update_Binary(path, &Zip, wipe_cache, UPDATE_BINARY_ZIP_TYPE); +#ifdef TW_AMONET + if (ret_val == INSTALL_SUCCESS) { + if (load_microloader() < 0) + ret_val = INSTALL_ERROR; + if (unpatch_part("/boot") < 0) + ret_val = INSTALL_ERROR; + if (ret_val == INSTALL_SUCCESS) + ret_val = Run_Update_Binary(path, &Zip, wipe_cache, UPDATE_BINARY_ZIP_TYPE); + if (patch_part("/boot") < 0) + ret_val = INSTALL_ERROR; + if (patch_part("/recovery") < 0) + ret_val = INSTALL_ERROR; + } +#else + ret_val = Run_Update_Binary(path, &Zip, wipe_cache, UPDATE_BINARY_ZIP_TYPE); +#endif } } else { if (Zip.EntryExists(AB_OTA)) { LOGINFO("AB zip\n"); + gui_msg(Msg(msg::kHighlight, "flash_ab_inactive=Flashing A/B zip to inactive slot: {1}")(PartitionManager.Get_Active_Slot_Display()=="A"?"B":"A")); + // We need this so backuptool can do its magic + bool system_mount_state = PartitionManager.Is_Mounted_By_Path(PartitionManager.Get_Android_Root_Path()); + bool vendor_mount_state = PartitionManager.Is_Mounted_By_Path("/vendor"); + PartitionManager.Mount_By_Path(PartitionManager.Get_Android_Root_Path(), true); + PartitionManager.Mount_By_Path("/vendor", true); + TWFunc::Exec_Cmd("cp -f /sbin/sh /tmp/sh"); + mount("/tmp/sh", "/system/bin/sh", "auto", MS_BIND, NULL); ret_val = Run_Update_Binary(path, &Zip, wipe_cache, AB_OTA_ZIP_TYPE); + umount("/system/bin/sh"); + unlink("/tmp/sh"); + if (!vendor_mount_state) + PartitionManager.UnMount_By_Path("/vendor", true); + if (!system_mount_state) + PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), true); + gui_warn("flash_ab_reboot=To flash additional zips, please reboot recovery to switch to the updated slot."); + DataManager::GetValue(TW_AUTO_REFLASHTWRP_VAR, reflashtwrp); + if (reflashtwrp) { + twrpRepacker repacker; + repacker.Flash_Current_Twrp(); + } } else { if (Zip.EntryExists("ui.xml")) { LOGINFO("TWRP theme zip\n"); diff --git a/twinstall.h b/twinstall.h index f60dd26ce0..406ab6fb93 100644 --- a/twinstall.h +++ b/twinstall.h @@ -1,6 +1,6 @@ #ifndef RECOVERY_TWINSTALL_H_ #define RECOVERY_TWINSTALL_H_ -int TWinstall_zip(const char* path, int* wipe_cache); +int TWinstall_zip(const char* path, int* wipe_cache, bool check_for_digest = false); #endif // RECOVERY_TWINSTALL_H_ diff --git a/twrp-functions.cpp b/twrp-functions.cpp index 4386ff6f49..c0fe704df9 100755 --- a/twrp-functions.cpp +++ b/twrp-functions.cpp @@ -59,15 +59,22 @@ extern "C" { #include "libcrecovery/common.h" } +#ifdef TW_INCLUDE_LIBRESETPROP + #include +#endif + struct selabel_handle *selinux_handle; /* Execute a command */ -int TWFunc::Exec_Cmd(const string& cmd, string &result) { +int TWFunc::Exec_Cmd(const string& cmd, string &result, bool combine_stderr) { FILE* exec; char buffer[130]; int ret = 0; - exec = __popen(cmd.c_str(), "r"); - if (!exec) return -1; + std::string popen_cmd = cmd; + if (combine_stderr) + popen_cmd = cmd + " 2>&1"; + exec = __popen(popen_cmd.c_str(), "r"); + while (!feof(exec)) { if (fgets(buffer, 128, exec) != NULL) { result += buffer; @@ -517,14 +524,14 @@ void TWFunc::Copy_Log(string Source, string Destination) { if (type == COMPRESSED) { std::string destFileBuffer; std::string getCompressedContents = "pigz -c -d " + Destination; - if (Exec_Cmd(getCompressedContents, destFileBuffer) < 0) { + if (Exec_Cmd(getCompressedContents, destFileBuffer, false) < 0) { LOGINFO("Unable to get destination logfile contents.\n"); return; } destLogBuffer.append(destFileBuffer); } } else if (Path_Exists(uncompressedLog)) { - std::ifstream uncompressedIfs(uncompressedLog); + std::ifstream uncompressedIfs(uncompressedLog.c_str()); std::stringstream uncompressedSS; uncompressedSS << uncompressedIfs.rdbuf(); uncompressedIfs.close(); @@ -533,7 +540,7 @@ void TWFunc::Copy_Log(string Source, string Destination) { std::remove(uncompressedLog.c_str()); } - std::ifstream ifs(Source); + std::ifstream ifs(Source.c_str()); std::stringstream ss; ss << ifs.rdbuf(); std::string srcLogBuffer(ss.str()); @@ -580,11 +587,11 @@ void TWFunc::Copy_Log(string Source, string Destination) { } void TWFunc::Update_Log_File(void) { - std::string recoveryDir = get_cache_dir() + "recovery/"; + std::string recoveryDir = get_log_dir() + "recovery/"; - if (get_cache_dir() == NON_AB_CACHE_DIR) { - if (!PartitionManager.Mount_By_Path(NON_AB_CACHE_DIR, false)) { - LOGINFO("Failed to mount %s for TWFunc::Update_Log_File\n", NON_AB_CACHE_DIR); + if (get_log_dir() == CACHE_LOGS_DIR) { + if (!PartitionManager.Mount_By_Path(CACHE_LOGS_DIR, false)) { + LOGINFO("Failed to mount %s for TWFunc::Update_Log_File\n", CACHE_LOGS_DIR); } } @@ -616,7 +623,7 @@ void TWFunc::Update_Log_File(void) { } } - if (get_cache_dir() == NON_AB_CACHE_DIR) { + if (get_log_dir() == CACHE_LOGS_DIR) { if (PartitionManager.Mount_By_Path("/cache", false)) { if (unlink("/cache/recovery/command") && errno != ENOENT) { LOGINFO("Can't unlink %s\n", "/cache/recovery/command"); @@ -637,8 +644,10 @@ int TWFunc::tw_reboot(RebootCommand command) { DataManager::Flush(); Update_Log_File(); + // Always force a sync before we reboot sync(); + std::string err; switch (command) { case rb_current: @@ -666,6 +675,15 @@ int TWFunc::tw_reboot(RebootCommand command) return property_set(ANDROID_RB_PROPERTY, "reboot,bootloader"); #else return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, (void*) "bootloader"); +#endif + case rb_hacked_bl: + if(!amonet_bootloader_message((void*)&err)) { + LOGERR("%s\n", err.c_str()); + } +#ifdef ANDROID_RB_PROPERTY + return property_set(ANDROID_RB_PROPERTY, "reboot,recovery"); +#else + return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, (void*) "recovery"); #endif case rb_poweroff: check_and_run_script("/sbin/poweroff.sh", "power off"); @@ -756,11 +774,11 @@ int TWFunc::copy_file(string src, string dst, int mode) { PartitionManager.Mount_By_Path(src, false); PartitionManager.Mount_By_Path(dst, false); if (!Path_Exists(src)) { - LOGINFO("Unable to find source file %s\n", src.c_str()); + LOGINFO("Path %s does not exist. Unable to copy %s\n", src.c_str(), dst.c_str()); return -1; } - std::ifstream srcfile(src, ios::binary); - std::ofstream dstfile(dst, ios::binary); + std::ifstream srcfile(src.c_str(), ios::binary); + std::ofstream dstfile(dst.c_str(), ios::binary); dstfile << srcfile.rdbuf(); if (!dstfile.bad()) { LOGINFO("Copied file %s to %s\n", src.c_str(), dst.c_str()); @@ -891,19 +909,23 @@ string TWFunc::Get_Current_Date() { } string TWFunc::System_Property_Get(string Prop_Name) { - bool mount_state = PartitionManager.Is_Mounted_By_Path(PartitionManager.Get_Android_Root_Path()); + return System_Property_Get(Prop_Name, PartitionManager, PartitionManager.Get_Android_Root_Path(), "build.prop"); +} + +string TWFunc::System_Property_Get(string Prop_Name, TWPartitionManager &PartitionManager, string Mount_Point, string prop_file_name) { + bool mount_state = PartitionManager.Is_Mounted_By_Path(Mount_Point); std::vector buildprop; string propvalue; - if (!PartitionManager.Mount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) + if (!PartitionManager.Mount_By_Path(Mount_Point, true)) return propvalue; - string prop_file = "/system/build.prop"; + string prop_file = Mount_Point + "/" + prop_file_name; if (!TWFunc::Path_Exists(prop_file)) - prop_file = PartitionManager.Get_Android_Root_Path() + "/system/build.prop"; // for devices with system as a root file system (e.g. Pixel) + prop_file = Mount_Point + "/system/" + prop_file_name; // for devices with system as a root file system (e.g. Pixel) if (TWFunc::read_file(prop_file, buildprop) != 0) { - LOGINFO("Unable to open build.prop for getting '%s'.\n", Prop_Name.c_str()); + LOGINFO("Unable to open %s for getting '%s'.\n", prop_file_name.c_str(), Prop_Name.c_str()); DataManager::SetValue(TW_BACKUP_NAME, Get_Current_Date()); if (!mount_state) - PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), false); + PartitionManager.UnMount_By_Path(Mount_Point, false); return propvalue; } int line_count = buildprop.size(); @@ -916,12 +938,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(PartitionManager.Get_Android_Root_Path(), false); + PartitionManager.UnMount_By_Path(Mount_Point, false); return propvalue; } } if (!mount_state) - PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), false); + PartitionManager.UnMount_By_Path(Mount_Point, false); return propvalue; } @@ -1056,6 +1078,16 @@ void TWFunc::Fixup_Time_On_Boot(const string& time_paths /* = "" */) } if (!fixed) { +#ifdef TW_QCOM_ATS_OFFSET + // Offset is the difference between the current time and the time since_epoch + // To calculate the offset in Android, the following expression (from a root shell) can be used: + // echo "$(( ($(date +%s) - $(cat /sys/class/rtc/rtc0/since_epoch)) ))" + // Add 3 zeros to the output and use that in the TW_QCOM_ATS_OFFSET flag in your BoardConfig.mk + // For example, if the result of the calculation is 1642433544, use 1642433544000 as the offset + offset = (uint64_t) TW_QCOM_ATS_OFFSET; + DataManager::SetValue("tw_qcom_ats_offset", (unsigned long long) offset, 1); + LOGINFO("TWFunc::Fixup_Time: Setting time offset from TW_QCOM_ATS_OFFSET, offset %llu\n", (unsigned long long) offset); +#else // Failed to get offset from ats file, check twrp settings unsigned long long value; if (DataManager::GetValue("tw_qcom_ats_offset", value) < 0) { @@ -1065,6 +1097,7 @@ void TWFunc::Fixup_Time_On_Boot(const string& time_paths /* = "" */) LOGINFO("TWFunc::Fixup_Time: Setting time offset from twrp setting file, offset %llu\n", (unsigned long long) offset); // Do not consider the settings file as a definitive answer, keep fixed=false so next run will try ats files again } +#endif } gettimeofday(&tv, NULL); @@ -1213,12 +1246,23 @@ void TWFunc::copy_kernel_log(string curr_storage) { std::string dmesgCmd = "/sbin/dmesg"; std::string result; - Exec_Cmd(dmesgCmd, result); + Exec_Cmd(dmesgCmd, result, false); write_to_file(dmesgDst, result); gui_msg(Msg("copy_kernel_log=Copied kernel log to {1}")(dmesgDst)); tw_set_default_metadata(dmesgDst.c_str()); } +void TWFunc::copy_logcat(string curr_storage) { + std::string logcatDst = curr_storage + "/logcat.txt"; + std::string logcatCmd = "logcat -d"; + + std::string result; + Exec_Cmd(logcatCmd, result, false); + write_to_file(logcatDst, result); + gui_msg(Msg("copy_logcat=Copied logcat to {1}")(logcatDst)); + tw_set_default_metadata(logcatDst.c_str()); +} + bool TWFunc::isNumber(string strtocheck) { int num = 0; std::istringstream iss(strtocheck); @@ -1238,20 +1282,17 @@ int TWFunc::stream_adb_backup(string &Restore_Name) { return ret; } -std::string TWFunc::get_cache_dir() { - if (PartitionManager.Find_Partition_By_Path(NON_AB_CACHE_DIR) == NULL) { - if (PartitionManager.Find_Partition_By_Path(AB_CACHE_DIR) == NULL) { - if (PartitionManager.Find_Partition_By_Path(PERSIST_CACHE_DIR) == NULL) { - LOGINFO("Unable to find a directory to store TWRP logs."); - return ""; - } - return PERSIST_CACHE_DIR; +std::string TWFunc::get_log_dir() { + if (PartitionManager.Find_Partition_By_Path(CACHE_LOGS_DIR) == NULL) { + if (PartitionManager.Find_Partition_By_Path(DATA_LOGS_DIR) == NULL) { + LOGINFO("Unable to find a directory to store TWRP logs."); + return ""; } else { - return AB_CACHE_DIR; + return DATA_LOGS_DIR; } } else { - return NON_AB_CACHE_DIR; + return CACHE_LOGS_DIR; } } @@ -1274,12 +1315,12 @@ void TWFunc::check_selinux_support() { printf("SELinux contexts loaded from /file_contexts\n"); { // Check to ensure SELinux can be supported by the kernel char *contexts = NULL; - std::string cacheDir = TWFunc::get_cache_dir(); + std::string cacheDir = TWFunc::get_log_dir(); std::string se_context_check = cacheDir + "recovery/"; int ret = 0; - if (cacheDir == NON_AB_CACHE_DIR) { - PartitionManager.Mount_By_Path(NON_AB_CACHE_DIR, false); + if (cacheDir == CACHE_LOGS_DIR) { + PartitionManager.Mount_By_Path(CACHE_LOGS_DIR, false); } if (TWFunc::Path_Exists(se_context_check)) { ret = lgetfilecon(se_context_check.c_str(), &contexts); @@ -1298,21 +1339,223 @@ void TWFunc::check_selinux_support() { } bool TWFunc::Is_TWRP_App_In_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)) - install_path = base_path + "/app"; - install_path += "/twrpapp"; - if (TWFunc::Path_Exists(install_path)) { - LOGINFO("App found at '%s'\n", install_path.c_str()); - DataManager::SetValue("tw_app_installed_in_system", 1); - return true; - } + bool is_system_mounted = true; + if(!PartitionManager.Is_Mounted_By_Path(PartitionManager.Get_Android_Root_Path())) { + is_system_mounted = false; + 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)) + install_path = base_path + "/app"; + install_path += "/twrpapp"; + if (TWFunc::Path_Exists(install_path)) { + LOGINFO("App found at '%s'\n", install_path.c_str()); + DataManager::SetValue("tw_app_installed_in_system", 1); + return true; } + if (!is_system_mounted) + PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), false); DataManager::SetValue("tw_app_installed_in_system", 0); return false; } + +void TWFunc::checkforapp(){ + + string sdkverstr = System_Property_Get("ro.build.version.sdk"); + int sdkver = 0; + if (!sdkverstr.empty()) { + sdkver = atoi(sdkverstr.c_str()); + } + if (sdkver <= 13) { + if (sdkver == 0) + LOGINFO("Unable to read sdk version from build prop\n"); + else + LOGINFO("SDK version too low for TWRP app (%i < 14)\n", sdkver); + DataManager::SetValue("tw_app_install_status", 1); // 0 = no status, 1 = not installed, 2 = already installed or do not install + goto exit; + } + if (Is_TWRP_App_In_System()) { + DataManager::SetValue("tw_app_install_status", 2); // 0 = no status, 1 = not installed, 2 = already installed or do not install + goto exit; + } + if (PartitionManager.Mount_By_Path("/data", false)) { + const char parent_path[] = "/data/app"; + const char app_prefix[] = "me.twrp.twrpapp-"; + DIR *d = opendir(parent_path); + if (d) { + struct dirent *p; + while ((p = readdir(d))) { + if (p->d_type != DT_DIR || strlen(p->d_name) < strlen(app_prefix) || strncmp(p->d_name, app_prefix, strlen(app_prefix))) + continue; + closedir(d); + LOGINFO("App found at '%s/%s'\n", parent_path, p->d_name); + DataManager::SetValue("tw_app_install_status", 2); // 0 = no status, 1 = not installed, 2 = already installed or do not install + goto exit; + } + closedir(d); + } + } else { + LOGINFO("Data partition cannot be mounted during app check\n"); + DataManager::SetValue("tw_app_install_status", 2); // 0 = no status, 1 = not installed, 2 = already installed or do not install + } + + LOGINFO("App not installed\n"); + DataManager::SetValue("tw_app_install_status", 1); // 0 = no status, 1 = not installed, 2 = already installed +exit: + return; + +} + +int TWFunc::Property_Override(string Prop_Name, string Prop_Value) { +#ifdef TW_INCLUDE_LIBRESETPROP + return setprop(Prop_Name.c_str(), Prop_Value.c_str(), false); +#else + return -2; +#endif +} + +#ifdef USE_EXT4 +bool TWFunc::Get_Encryption_Policy(ext4_encryption_policy &policy, std::string path) { +#ifdef TW_INCLUDE_FBE + if (!TWFunc::Path_Exists(path)) { + LOGERR("Unable to find %s to get policy\n", path.c_str()); + return false; + } + if (!e4crypt_policy_get_struct(path.c_str(), &policy)) { + LOGERR("No policy set for path %s\n", path.c_str()); + return false; + } +#endif + return true; +} + +bool TWFunc::Set_Encryption_Policy(std::string path, const ext4_encryption_policy &policy) { +#ifdef TW_INCLUDE_FBE + if (!TWFunc::Path_Exists(path)) { + LOGERR("unable to find %s to set policy\n", path.c_str()); + return false; + } + char binary_policy[EXT4_KEY_DESCRIPTOR_SIZE]; + char policy_hex[EXT4_KEY_DESCRIPTOR_SIZE_HEX]; + policy_to_hex(binary_policy, policy_hex); + if (!e4crypt_policy_set_struct(path.c_str(), &policy)) { + LOGERR("unable to set policy for path: %s\n", path.c_str()); + return false; + } +#endif + return true; +} +#endif + +string TWFunc::Check_For_TwrpFolder(){ + string oldFolder = ""; + vector customTWRPFolders; + string mainPath = DataManager::GetCurrentStoragePath(); + DIR* d; + struct dirent* de; + + if (DataManager::GetIntValue(TW_IS_ENCRYPTED)) { + goto exit; + } + + + d = opendir(mainPath.c_str()); + if (d == NULL) { + goto exit; + } + + while ((de = readdir(d)) != NULL) { + string name = de->d_name; + string fullPath = mainPath + '/' + name; + unsigned char type = de->d_type; + + if (name == "." || name == "..") continue; + + if (type == DT_UNKNOWN) { + type = Get_D_Type_From_Stat(fullPath); + } + + if (type == DT_DIR && Path_Exists(fullPath + '/' + TW_SETTINGS_FILE)) { + if ('/' + name == TW_DEFAULT_RECOVERY_FOLDER) { + oldFolder = name; + } else { + customTWRPFolders.push_back(name); + } + } + } + + closedir(d); + + if (oldFolder == "" && customTWRPFolders.empty()) { + LOGINFO("No recovery folder found. Using default folder.\n"); + goto exit; + } else if (customTWRPFolders.empty()) { + LOGINFO("No custom recovery folder found. Using TWRP as default.\n"); + goto exit; + } else { + if (customTWRPFolders.size() > 1) { + LOGINFO("More than one custom recovery folder found. Using first one from the list.\n"); + } else { + LOGINFO("One custom recovery folder found.\n"); + } + string customPath = '/' + customTWRPFolders.at(0); + + if (Path_Exists(mainPath + TW_DEFAULT_RECOVERY_FOLDER)) { + string oldBackupFolder = mainPath + TW_DEFAULT_RECOVERY_FOLDER + "/BACKUPS/" + DataManager::GetStrValue("device_id"); + string newBackupFolder = mainPath + customPath + "/BACKUPS/" + DataManager::GetStrValue("device_id"); + + if (Path_Exists(oldBackupFolder)) { + vector backups; + d = opendir(oldBackupFolder.c_str()); + + if (d != NULL) { + while ((de = readdir(d)) != NULL) { + string name = de->d_name; + unsigned char type = de->d_type; + + if (name == "." || name == "..") continue; + + if (type == DT_UNKNOWN) { + type = Get_D_Type_From_Stat(mainPath + '/' + name); + } + + if (type == DT_DIR) { + backups.push_back(name); + } + } + closedir(d); + } + + for (auto it = backups.begin(); it != backups.end(); it++) { + Exec_Cmd("mv -f \"" + oldBackupFolder + '/' + *it + "\" \"" + newBackupFolder + '/' + *it + (Path_Exists(newBackupFolder + '/' + *it) ? "_new\"" : "\"")); + } + } + Exec_Cmd("rm -rf \"" + mainPath + TW_DEFAULT_RECOVERY_FOLDER + '\"'); + } + + return customPath; + } + +exit: + return TW_DEFAULT_RECOVERY_FOLDER; +} + +bool TWFunc::Check_Xml_Format(const char* filename) { + std::string buffer(' ', 4); + std::string abx_hdr("ABX\x00", 4); + std::ifstream File; + File.open(filename); + if (File.is_open()) { + File.get(&buffer[0], buffer.size()); + File.close(); + // Android Binary Xml start from these bytes + if(!buffer.compare(0, abx_hdr.size(), abx_hdr)) + return false; // bad format, not possible to parse + } + return true; // good format, possible to parse +} + #endif // ndef BUILD_TWRPTAR_MAIN diff --git a/twrp-functions.hpp b/twrp-functions.hpp index 8cea321b54..0f8ffb61a8 100755 --- a/twrp-functions.hpp +++ b/twrp-functions.hpp @@ -22,13 +22,23 @@ #include #include +#ifdef USE_FSCRYPT +#include +#endif +#ifdef USE_EXT4 +#include "ext4crypt_tar.h" +#endif + #include "twrpDigest/twrpDigest.hpp" +#ifndef BUILD_TWRPTAR_MAIN +#include "partitions.hpp" +#endif + using namespace std; -#define NON_AB_CACHE_DIR "/cache/" -#define AB_CACHE_DIR "/data/cache/" -#define PERSIST_CACHE_DIR "/persist/cache/" +#define CACHE_LOGS_DIR "/cache/" // For devices with a dedicated cache partition +#define DATA_LOGS_DIR "/data/" // For devices that do not have a dedicated cache partition typedef enum { @@ -39,6 +49,7 @@ typedef enum rb_bootloader, // May also be fastboot rb_download, rb_edl, + rb_hacked_bl, } RebootCommand; enum Archive_Type { @@ -48,6 +59,7 @@ enum Archive_Type { COMPRESSED_ENCRYPTED }; + // Partition class class TWFunc { @@ -56,8 +68,8 @@ class TWFunc static string Get_Path(const string& Path); // Trims everything after the last / in the string static string Get_Filename(const string& Path); // Trims the path off of a filename - static int Exec_Cmd(const string& cmd, string &result); //execute a command and return the result as a string by reference - static int Exec_Cmd(const string& cmd, bool Show_Errors = true); //execute a command, displays an error to the GUI if Show_Errors is true, Show_Errors is true by default + static int Exec_Cmd(const string& cmd, string &result, bool combine_stderr); //execute a command and return the result as a string by reference, set combined_stderror to add stderr + static int Exec_Cmd(const string& cmd, bool Show_Errors = true); //execute a command, displays an error to the GUI if Show_Errors is true, Show_Errors is true by default static int Wait_For_Child(pid_t pid, int *status, string Child_Name, bool Show_Errors = true); // Waits for pid to exit and checks exit status, displays an error to the GUI if Show_Errors is true which is the default static int Wait_For_Child_Timeout(pid_t pid, int *status, const string& Child_Name, int timeout); // Waits for a pid to exit until the timeout is hit. If timeout is hit, kill the chilld. static bool Path_Exists(string Path); // Returns true if the path exists @@ -90,6 +102,7 @@ class TWFunc static int write_to_file(const string& fn, const string& line); //write to file static bool Try_Decrypting_Backup(string Restore_Path, string Password); // true for success, false for failed to decrypt static string System_Property_Get(string Prop_Name); // Returns value of Prop_Name from reading /system/build.prop + static string System_Property_Get(string Prop_Name, TWPartitionManager &PartitionManager, string Mount_Point, string prop_file_name); // Returns value of Prop_Name from reading provided prop file static string Get_Current_Date(void); // Returns the current date in ccyy-m-dd--hh-nn-ss format static void Auto_Generate_Backup_Name(); // Populates TW_BACKUP_NAME with a backup name based on current date and ro.build.display.id from /system/build.prop static void Fixup_Time_On_Boot(const string& time_paths = ""); // Fixes time on devices which need it (time_paths is a space separated list of paths to check for ats_* files) @@ -102,11 +115,20 @@ class TWFunc static void Disable_Stock_Recovery_Replace(); // Disable stock ROMs from replacing TWRP with stock recovery static unsigned long long IOCTL_Get_Block_Size(const char* block_device); static void copy_kernel_log(string curr_storage); // Copy Kernel Log to Current Storage (PSTORE/KMSG) + static void copy_logcat(string curr_storage); // Copy Logcat to Current Storage static bool isNumber(string strtocheck); // return true if number, false if not a number static int stream_adb_backup(string &Restore_Name); // Tell ADB Backup to Stream to TWRP from GUI selection - static std::string get_cache_dir(); // return the cache partition existence + static std::string get_log_dir(); // return recovery log storage directory static void check_selinux_support(); // print whether selinux support is enabled to console static bool Is_TWRP_App_In_System(); // Check if the TWRP app is installed in the system partition + static void checkforapp(); + static int Property_Override(string Prop_Name, string Prop_Value); // Override properties (including ro. properties) +#ifdef USE_EXT4 + static bool Get_Encryption_Policy(ext4_encryption_policy &policy, std::string path); // return encryption policy for path + static bool Set_Encryption_Policy(std::string path, const ext4_encryption_policy &policy); // set encryption policy for path +#endif + static string Check_For_TwrpFolder(); + static bool Check_Xml_Format(const char* filename); // Return whether a xml is in plain xml or ABX format private: static void Copy_Log(string Source, string Destination); diff --git a/twrp.cpp b/twrp.cpp index 95e376b5a5..2d5ab3f9f5 100755 --- a/twrp.cpp +++ b/twrp.cpp @@ -43,6 +43,14 @@ extern "C" { #include "twrp-functions.hpp" #include "data.hpp" #include "partitions.hpp" + +#if SDK_VERSION >= 24 +#include +#elif SDK_VERSION == 23 +#include +#else +#include +#endif #include "openrecoveryscript.hpp" #include "variables.h" #include "twrpAdbBuFifo.hpp" @@ -109,16 +117,97 @@ int main(int argc, char **argv) { // Load default values to set DataManager constants and handle ifdefs DataManager::SetDefaultValues(); +#ifndef TW_NO_SCREEN printf("Starting the UI...\n"); gui_init(); +#endif printf("=> Linking mtab\n"); symlink("/proc/mounts", "/etc/mtab"); std::string fstab_filename = "/etc/twrp.fstab"; if (!TWFunc::Path_Exists(fstab_filename)) { fstab_filename = "/etc/recovery.fstab"; } + + // Begin SAR detection + { + TWPartitionManager SarPartitionManager; + printf("=> Processing %s for SAR-detection\n", fstab_filename.c_str()); + if (!SarPartitionManager.Process_Fstab(fstab_filename, 1, 1)) { + LOGERR("Failing out of recovery due to problem with fstab.\n"); + return -1; + } + + mkdir("/s", 0755); + +#if defined(AB_OTA_UPDATER) || defined(__ANDROID_API_Q__) + bool fallback_sar = true; +#else + bool fallback_sar = property_get_bool("ro.build.system_root_image", false); +#endif + + if(SarPartitionManager.Mount_By_Path("/s", false)) { + if (TWFunc::Path_Exists("/s/build.prop")) { + LOGINFO("SAR-DETECT: Non-SAR System detected\n"); + property_set("ro.twrp.sar", "false"); + rmdir("/system_root"); + } else if (TWFunc::Path_Exists("/s/system/build.prop")) { + LOGINFO("SAR-DETECT: SAR System detected\n"); + property_set("ro.twrp.sar", "true"); + } else { + LOGINFO("SAR-DETECT: No build.prop found, falling back to %s\n", fallback_sar ? "SAR" : "Non-SAR"); + property_set("ro.twrp.sar", fallback_sar ? "true" : "false"); + } + +// We are doing this here during SAR-detection, since we are mounting the system-partition anyway +// This way we don't need to remount it later, just for overriding properties +#if defined(TW_INCLUDE_LIBRESETPROP) && defined(TW_OVERRIDE_SYSTEM_PROPS) + stringstream override_props(EXPAND(TW_OVERRIDE_SYSTEM_PROPS)); + string current_prop; + std::vector build_prop_list = {"build.prop"}; +#ifdef TW_SYSTEM_BUILD_PROP_ADDITIONAL_PATHS + std::vector additional_build_prop_list = TWFunc::Split_String(TW_SYSTEM_BUILD_PROP_ADDITIONAL_PATHS, ";"); + build_prop_list.insert(build_prop_list.end(), additional_build_prop_list.begin(), additional_build_prop_list.end()); +#endif + while (getline(override_props, current_prop, ';')) { + string other_prop; + if (current_prop.find("=") != string::npos) { + other_prop = current_prop.substr(current_prop.find("=") + 1); + current_prop = current_prop.substr(0, current_prop.find("=")); + } else { + other_prop = current_prop; + } + other_prop = android::base::Trim(other_prop); + current_prop = android::base::Trim(current_prop); + + for (auto&& prop_file:build_prop_list) { + string sys_val = TWFunc::System_Property_Get(other_prop, SarPartitionManager, "/s", prop_file); + if (!sys_val.empty()) { + LOGINFO("Overriding %s with value: \"%s\" from system property %s from %s\n", current_prop.c_str(), sys_val.c_str(), other_prop.c_str(), prop_file.c_str()); + int error = TWFunc::Property_Override(current_prop, sys_val); + if (error) { + LOGERR("Failed overriding property %s, error_code: %d\n", current_prop.c_str(), error); + } + break; + } else { + LOGINFO("Not overriding %s with empty value from system property %s from %s\n", current_prop.c_str(), other_prop.c_str(), prop_file.c_str()); + } + } + } +#endif + SarPartitionManager.UnMount_By_Path("/s", false); + } else { + LOGINFO("SAR-DETECT: Could not mount system partition, falling back to %s\n", fallback_sar ? "SAR":"Non-SAR"); + property_set("ro.twrp.sar", fallback_sar ? "true" : "false"); + } + + rmdir("/s"); + + TWFunc::check_and_run_script("/sbin/sarsetup.sh", "SAR"); + } + // End SAR detection + printf("=> Processing %s\n", fstab_filename.c_str()); - if (!PartitionManager.Process_Fstab(fstab_filename, 1)) { + if (!PartitionManager.Process_Fstab(fstab_filename, 1, 0)) { LOGERR("Failing out of recovery due to problem with fstab.\n"); return -1; } @@ -127,7 +216,6 @@ int main(int argc, char **argv) { gui_loadResources(); bool Shutdown = false; - bool SkipDecryption = false; string Send_Intent = ""; { TWPartition* misc = PartitionManager.Find_Partition_By_Path("/misc"); @@ -162,9 +250,6 @@ int main(int argc, char **argv) { string ORSCommand = "install "; ORSCommand.append(ptr); - // If we have a map of blocks we don't need to mount data. - SkipDecryption = *ptr == '@'; - if (!OpenRecoveryScript::Insert_ORS_Command(ORSCommand)) break; } else @@ -232,17 +317,15 @@ int main(int argc, char **argv) { // Offer to decrypt if the device is encrypted if (DataManager::GetIntValue(TW_IS_ENCRYPTED) != 0) { - if (SkipDecryption) { - LOGINFO("Skipping decryption\n"); + LOGINFO("Is encrypted, do decrypt page first\n"); + if (DataManager::GetIntValue(TW_IS_FBE)) + DataManager::SetValue("tw_crypto_user_id", "0"); + if (gui_startPage("decrypt", 1, 1) != 0) { + LOGERR("Failed to start decrypt GUI page.\n"); } else { - LOGINFO("Is encrypted, do decrypt page first\n"); - if (gui_startPage("decrypt", 1, 1) != 0) { - LOGERR("Failed to start decrypt GUI page.\n"); - } else { - // Check for and load custom theme if present - TWFunc::check_selinux_support(); - gui_loadCustomResources(); - } + // Check for and load custom theme if present + TWFunc::check_selinux_support(); + gui_loadCustomResources(); } } else if (datamedia) { TWFunc::check_selinux_support(); @@ -254,19 +337,25 @@ int main(int argc, char **argv) { } // Fixup the RTC clock on devices which require it - if (crash_counter == 0) - TWFunc::Fixup_Time_On_Boot(); + if (crash_counter == 0) TWFunc::Fixup_Time_On_Boot(); // Read the settings file TWFunc::Update_Log_File(); + DataManager::LoadTWRPFolderInfo(); DataManager::ReadSettingsFile(); PageManager::LoadLanguage(DataManager::GetStrValue("tw_language")); +#ifndef TW_NO_SCREEN GUIConsole::Translate_Now(); +#endif // Run any outstanding OpenRecoveryScript - std::string cacheDir = TWFunc::get_cache_dir(); + std::string cacheDir = TWFunc::get_log_dir(); + if (cacheDir == DATA_LOGS_DIR) + cacheDir = "/data/cache"; std::string orsFile = cacheDir + "/recovery/openrecoveryscript"; - if ((DataManager::GetIntValue(TW_IS_ENCRYPTED) == 0 || SkipDecryption) && (TWFunc::Path_Exists(SCRIPT_FILE_TMP) || TWFunc::Path_Exists(orsFile))) { + + if (TWFunc::Path_Exists(SCRIPT_FILE_TMP) || + (DataManager::GetIntValue(TW_IS_ENCRYPTED) == 0 && TWFunc::Path_Exists(orsFile))) { OpenRecoveryScript::Run_OpenRecoveryScript(); } @@ -293,6 +382,19 @@ int main(int argc, char **argv) { } #endif +#ifdef TW_BOOT_MENU + // Check the cmdline to see if boot_reason=0 + char line[2048]; + FILE *fp = fopen("/proc/cmdline", "rt"); + if (fp != NULL) { + fgets(line, sizeof(line), fp); + fclose(fp); // cmdline is only one line long + if(strstr(line, "boot_reason=0") && strstr(line, "y_cable=1")) { + boot_menu(); + } + } +#endif + #ifndef TW_OEM_BUILD // Check if system has never been changed TWPartition* sys = PartitionManager.Find_Partition_By_Path(PartitionManager.Get_Android_Root_Path()); @@ -322,6 +424,8 @@ int main(int argc, char **argv) { twrpAdbBuFifo *adb_bu_fifo = new twrpAdbBuFifo(); adb_bu_fifo->threadAdbBuFifo(); + TWFunc::checkforapp(); //Checking compatibility for TWRP app + // Launch the main GUI gui_start(); @@ -347,6 +451,8 @@ int main(int argc, char **argv) { TWFunc::tw_reboot(rb_download); else if (Reboot_Arg == "edl") TWFunc::tw_reboot(rb_edl); + else if (Reboot_Arg == "hacked_bl") + TWFunc::tw_reboot(rb_hacked_bl); else TWFunc::tw_reboot(rb_system); diff --git a/twrpDigestDriver.cpp b/twrpDigestDriver.cpp index 074b6c3df5..af3141794c 100755 --- a/twrpDigestDriver.cpp +++ b/twrpDigestDriver.cpp @@ -70,12 +70,8 @@ bool twrpDigestDriver::Check_File_Digest(const string& Filename) { if (!TWFunc::Path_Exists(digestfile)) { delete digest; - if (Filename.find(".zip") == std::string::npos && Filename.find(".map") == std::string::npos) { - gui_msg(Msg(msg::kError, "no_digest_found=No digest file found for '{1}'. Please unselect Enable Digest verification to restore.")(Filename)); - } else { - return true; - } - return false; + gui_msg(Msg(msg::kWarning, "no_digest=Skipping Digest check: no Digest file found")); + return true; } diff --git a/twrpRepacker.cpp b/twrpRepacker.cpp new file mode 100755 index 0000000000..c50435c2dc --- /dev/null +++ b/twrpRepacker.cpp @@ -0,0 +1,296 @@ +/* + Copyright 2013 to 2020 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 . +*/ + +#include +#include + +#include "data.hpp" +#include "partitions.hpp" +#include "twrp-functions.hpp" +#include "twrpRepacker.hpp" +#include "twcommon.h" +#include "variables.h" +#include "gui/gui.hpp" + +bool twrpRepacker::Prepare_Empty_Folder(const std::string& Folder) { + if (TWFunc::Path_Exists(Folder)) + TWFunc::removeDir(Folder, false); + return TWFunc::Recursive_Mkdir(Folder); +} + +bool twrpRepacker::Backup_Image_For_Repack(TWPartition* Part, const std::string& Temp_Folder_Destination, + const bool Create_Backup, const std::string& Backup_Name) { + if (!Part) { + LOGERR("Partition was null!\n"); + return false; + } + if (!Prepare_Empty_Folder(Temp_Folder_Destination)) + return false; + std::string target_image = Temp_Folder_Destination + "boot.img"; + PartitionSettings part_settings; + part_settings.Part = Part; + if (Create_Backup) { + if (PartitionManager.Check_Backup_Name(Backup_Name, true, false) != 0) + return false; + DataManager::GetValue(TW_BACKUPS_FOLDER_VAR, part_settings.Backup_Folder); + part_settings.Backup_Folder = part_settings.Backup_Folder + "/" + TWFunc::Get_Current_Date() + " " + Backup_Name + "/"; + if (!TWFunc::Recursive_Mkdir(part_settings.Backup_Folder)) + return false; + } else + part_settings.Backup_Folder = Temp_Folder_Destination; + part_settings.adbbackup = false; + part_settings.generate_digest = false; + part_settings.generate_md5 = false; + part_settings.PM_Method = PM_BACKUP; + part_settings.progress = NULL; + pid_t not_a_pid = 0; + if (!Part->Backup(&part_settings, ¬_a_pid)) + return false; + std::string backed_up_image = part_settings.Backup_Folder; + backed_up_image += Part->Get_Backup_FileName(); + target_image = Temp_Folder_Destination + "boot.img"; + if (Create_Backup) { + std::string source = part_settings.Backup_Folder + Part->Get_Backup_FileName(); + if (TWFunc::copy_file(source, target_image, 0644) != 0) { + LOGERR("Failed to copy backup file '%s' to temp folder target '%s'\n", source.c_str(), target_image.c_str()); + return false; + } + } else { + if (rename(backed_up_image.c_str(), target_image.c_str()) != 0) { + LOGERR("Failed to rename '%s' to '%s'\n", backed_up_image.c_str(), target_image.c_str()); + return false; + } + } + original_ramdisk_format = Unpack_Image(target_image, Temp_Folder_Destination, false, false); + return !original_ramdisk_format.empty(); +} + +std::string twrpRepacker::Unpack_Image(const std::string& Source_Path, const std::string& Temp_Folder_Destination, + const bool Copy_Source, const bool Create_Destination) { + std::string txt_to_find = "RAMDISK_FMT"; + if (Create_Destination) { + if (!Prepare_Empty_Folder(Temp_Folder_Destination)) + return std::string(); + } + if (Copy_Source) { + std::string destination = Temp_Folder_Destination + "/boot.img"; + if (TWFunc::copy_file(Source_Path, destination, 0644)) + return std::string(); + } + std::string command = "cd " + Temp_Folder_Destination + " && /sbin/magiskboot unpack -h "; + command = command + "'" + Source_Path +"'"; + + std::string magisk_unpack_output; + int ret; + if ((ret = TWFunc::Exec_Cmd(command, magisk_unpack_output, true)) != 0) { + LOGINFO("Error unpacking %s, ret: %d!\n", Source_Path.c_str(), ret); + gui_msg(Msg(msg::kError, "unpack_error=Error unpacking image.")); + return std::string(); + } + size_t pos = magisk_unpack_output.find(txt_to_find) + txt_to_find.size(); + std::string ramdisk_format = magisk_unpack_output.substr(pos, magisk_unpack_output.size() - 1); + ramdisk_format.erase(std::remove(ramdisk_format.begin(), ramdisk_format.end(), '['), ramdisk_format.end()); + ramdisk_format.erase(std::remove(ramdisk_format.begin(), ramdisk_format.end(), ']'), ramdisk_format.end()); + ramdisk_format.erase(std::remove(ramdisk_format.begin(), ramdisk_format.end(), ' '), ramdisk_format.end()); + ramdisk_format.erase(std::remove(ramdisk_format.begin(), ramdisk_format.end(), '\n'), ramdisk_format.end()); + return ramdisk_format; +} + +bool twrpRepacker::Repack_Image_And_Flash(const std::string& Target_Image, const struct Repack_Options_struct& Repack_Options) { + bool recompress = false; + + if (!TWFunc::Path_Exists("/sbin/magiskboot")) { + LOGERR("Image repacking tool not present in this TWRP build!"); + return false; + } + DataManager::SetProgress(0); + PartitionManager.Update_System_Details(); + TWPartition* part = PartitionManager.Find_Partition_By_Path("/boot"); + if (part) + gui_msg(Msg("unpacking_image=Unpacking {1}...")(part->Get_Display_Name())); + else { + gui_msg(Msg(msg::kError, "unable_to_locate=Unable to locate {1}.")("/boot")); + return false; + } + if (!Backup_Image_For_Repack(part, REPACK_ORIG_DIR, Repack_Options.Backup_First, gui_lookup("repack", "Repack"))) + return false; + DataManager::SetProgress(.25); + if (Repack_Options.Type == REPLACE_RAMDISK_UNPACKED) { + if (!Prepare_Empty_Folder(REPACK_NEW_DIR)) + return false; + image_ramdisk_format = "gzip"; + } else { + gui_msg(Msg("unpacking_image=Unpacking {1}...")(Target_Image)); + image_ramdisk_format = Unpack_Image(Target_Image, REPACK_NEW_DIR, true); + } + if (image_ramdisk_format.empty()) + return false; + DataManager::SetProgress(.5); + gui_msg(Msg("repacking_image=Repacking {1}...")(part->Get_Display_Name())); + std::string path = REPACK_NEW_DIR; + if (Repack_Options.Type == REPLACE_KERNEL) { + // When we replace the kernel, what we really do is copy the boot partition ramdisk into the new image's folder + if (TWFunc::copy_file(REPACK_ORIG_DIR "ramdisk.cpio", REPACK_NEW_DIR "ramdisk.cpio", 0644)) { + LOGERR("Failed to copy ramdisk\n"); + return false; + } + } else if (Repack_Options.Type == REPLACE_RAMDISK_UNPACKED) { + if (TWFunc::copy_file(Target_Image, REPACK_ORIG_DIR "ramdisk.cpio", 0644)) { + LOGERR("Failed to copy ramdisk\n"); + return false; + } + if (TWFunc::copy_file(Target_Image, REPACK_NEW_DIR "ramdisk.cpio", 0644)) { + LOGERR("Failed to copy ramdisk\n"); + return false; + } + path = REPACK_ORIG_DIR; + } else if (Repack_Options.Type == REPLACE_RAMDISK) { + // Repack the ramdisk + if (TWFunc::copy_file(REPACK_NEW_DIR "ramdisk.cpio", REPACK_ORIG_DIR "ramdisk.cpio", 0644)) { + LOGERR("Failed to copy ramdisk\n"); + return false; + } + path = REPACK_ORIG_DIR; + } else { + LOGERR("Invalid repacking options specified\n"); + return false; + } + if (Repack_Options.Disable_Verity) + LOGERR("Disabling verity is not implemented yet\n"); + if (Repack_Options.Disable_Force_Encrypt) + LOGERR("Disabling force encrypt is not implemented yet\n"); + std::string command = "cd " + path + " && /sbin/magiskboot repack "; + if (original_ramdisk_format != image_ramdisk_format) { + recompress = true; + } + + command += path + "boot.img"; + + std::string orig_compressed_image(REPACK_ORIG_DIR); + orig_compressed_image += "ramdisk.cpio"; + std::string copy_compressed_image(REPACK_ORIG_DIR); + copy_compressed_image += "ramdisk-1.cpio"; + + if (recompress) { + std::string decompress_cmd = "/sbin/magiskboot decompress " + orig_compressed_image + " " + copy_compressed_image; + if (TWFunc::Exec_Cmd(decompress_cmd) != 0) { + gui_msg(Msg(msg::kError, "repack_error=Error repacking image.")); + return false; + } + std::rename(copy_compressed_image.c_str(), orig_compressed_image.c_str()); + } + + if (TWFunc::Exec_Cmd(command) != 0) { + gui_msg(Msg(msg::kError, "repack_error=Error repacking image.")); + return false; + } + + DataManager::SetProgress(.75); + std::string file = "new-boot.img"; + DataManager::SetValue("tw_flash_partition", "/boot;"); + if (!PartitionManager.Flash_Image(path, file)) { + LOGINFO("Error flashing new image\n"); + return false; + } + DataManager::SetProgress(1); + TWFunc::removeDir(REPACK_ORIG_DIR, false); + if (part->Is_SlotSelect()) { if (Repack_Options.Type == REPLACE_RAMDISK || Repack_Options.Type == REPLACE_RAMDISK_UNPACKED) { + LOGINFO("Switching slots to flash ramdisk to both partitions\n"); + string Current_Slot = PartitionManager.Get_Active_Slot_Display(); + if (Current_Slot == "A") + PartitionManager.Override_Active_Slot("B"); + else + PartitionManager.Override_Active_Slot("A"); + DataManager::SetProgress(.25); + if (!Backup_Image_For_Repack(part, REPACK_ORIG_DIR, Repack_Options.Backup_First, gui_lookup("repack", "Repack"))) + return false; + if (TWFunc::copy_file(REPACK_NEW_DIR "ramdisk.cpio", REPACK_ORIG_DIR "ramdisk.cpio", 0644)) { + LOGERR("Failed to copy ramdisk\n"); + return false; + } + path = REPACK_ORIG_DIR; + std::string command = "cd " + path + " && /sbin/magiskboot repack "; + + if (original_ramdisk_format != image_ramdisk_format) { + recompress = true; + } + command += path + "boot.img"; + + if (recompress) { + std::string decompress_cmd = "/sbin/magiskboot decompress " + orig_compressed_image + " " + copy_compressed_image; + if (TWFunc::Exec_Cmd(decompress_cmd) != 0) { + gui_msg(Msg(msg::kError, "repack_error=Error repacking image.")); + return false; + } + std::rename(copy_compressed_image.c_str(), orig_compressed_image.c_str()); + } + + if (TWFunc::Exec_Cmd(command) != 0) { + gui_msg(Msg(msg::kError, "repack_error=Error repacking image.")); + return false; + } + + if (TWFunc::Exec_Cmd(command) != 0) { + gui_msg(Msg(msg::kError, "repack_error=Error repacking image.")); + return false; + } + DataManager::SetProgress(.75); + std::string file = "new-boot.img"; + DataManager::SetValue("tw_flash_partition", "/boot;"); + if (!PartitionManager.Flash_Image(path, file)) { + LOGINFO("Error flashing new image\n"); + return false; + } + DataManager::SetProgress(1); + TWFunc::removeDir(REPACK_ORIG_DIR, false); + }} + TWFunc::removeDir(REPACK_NEW_DIR, false); + gui_msg(Msg(msg::kWarning, "repack_overwrite_warning=If device was previously rooted, then root has been overwritten and will need to be reinstalled.")); + string Current_Slot = PartitionManager.Get_Active_Slot_Display(); + if (Current_Slot == "A") + PartitionManager.Override_Active_Slot("B"); + else + PartitionManager.Override_Active_Slot("A"); + return true; +} + +bool twrpRepacker::Flash_Current_Twrp() { +if (!TWFunc::Path_Exists("/ramdisk-files.txt")) { + LOGERR("can not find ramdisk-files.txt"); + return false; + } + Repack_Options_struct Repack_Options; + Repack_Options.Disable_Verity = false; + Repack_Options.Disable_Force_Encrypt = false; + Repack_Options.Type = REPLACE_RAMDISK_UNPACKED; + Repack_Options.Backup_First = DataManager::GetIntValue("tw_repack_backup_first") != 0; + std::string verifyfiles = "cd / && sha256sum -c ramdisk-files.sha256sum"; + if (TWFunc::Exec_Cmd(verifyfiles) != 0) { + gui_msg(Msg(msg::kError, "modified_ramdisk_error=ramdisk files have been modified, unable to create ramdisk to flash, fastboot boot twrp and try this option again or use the Install Recovery Ramdisk option.")); + return false; + } + std::string command = "cd / && /sbin/cpio -H newc -o < ramdisk-files.txt > /tmp/currentramdisk.cpio && /sbin/gzip -f /tmp/currentramdisk.cpio"; + if (TWFunc::Exec_Cmd(command) != 0) { + gui_msg(Msg(msg::kError, "create_ramdisk_error=failed to create ramdisk to flash.")); + return false; + } + if (!Repack_Image_And_Flash("/tmp/currentramdisk.cpio.gz", Repack_Options)) + return false; + else + return true; +} diff --git a/twrpRepacker.hpp b/twrpRepacker.hpp new file mode 100755 index 0000000000..e71f3dcb4f --- /dev/null +++ b/twrpRepacker.hpp @@ -0,0 +1,50 @@ +/* + Copyright 2014 to 2020 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 . +*/ + +#include +#include "partitions.hpp" + +#ifndef TWRP_REPACKER +#define TWRP_REPACKER + +enum Repack_Type { + REPLACE_NONE = 0, + REPLACE_RAMDISK = 1, + REPLACE_KERNEL = 2, + REPLACE_RAMDISK_UNPACKED = 3, +}; + +struct Repack_Options_struct { + Repack_Type Type; + bool Backup_First; + bool Disable_Verity; + bool Disable_Force_Encrypt; +}; + +class twrpRepacker { + public: + bool Backup_Image_For_Repack(TWPartition* Part, const std::string& Temp_Folder_Destination, const bool Create_Backup, const std::string& Backup_Name); // Prepares an image for repacking by unpacking it to the temp folder destination + std::string Unpack_Image(const std::string& Source_Path, const std::string& Temp_Folder_Destination, const bool Copy_Source, const bool Create_Destination = true); // Prepares an image for repacking by unpacking it to the temp folder destination and return the ramdisk format + bool Repack_Image_And_Flash(const std::string& Target_Image, const struct Repack_Options_struct& Repack_Options); // Repacks the boot image with a new kernel or a new ramdisk + bool Flash_Current_Twrp(); + private: + bool Prepare_Empty_Folder(const std::string& Folder); // Creates an empty folder at Folder. If the folder already exists, the folder is deleted, then created + std::string original_ramdisk_format; // Ramdisk format of boot partition + std::string image_ramdisk_format; // Ramdisk format of boot image to repack from +}; +#endif // TWRP_REPACKER diff --git a/twrpTar.cpp b/twrpTar.cpp index d15eea6b9f..94667a5b4a 100644 --- a/twrpTar.cpp +++ b/twrpTar.cpp @@ -315,6 +315,7 @@ int twrpTar::createTarFork(pid_t *tar_fork_pid) { } /*if (pthread_attr_setstacksize(&tattr, 524288)) { LOGERR("Error setting pthread_attr_setstacksize\n"); + close(progress_pipe[1]); _exit(-1); }*/ @@ -874,10 +875,10 @@ void* twrpTar::extractMulti(void *cookie) { int twrpTar::addFilesToExistingTar(vector files, string fn) { char* charTarFile = (char*) fn.c_str(); - if (tar_open(&t, charTarFile, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) == -1) + if (tar_open(&t, charTarFile, NULL, O_CLOEXEC | O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) == -1) return -1; removeEOT(charTarFile); - if (tar_open(&t, charTarFile, NULL, O_WRONLY | O_APPEND | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) == -1) + if (tar_open(&t, charTarFile, NULL, O_CLOEXEC | O_WRONLY | O_APPEND | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) == -1) return -1; for (unsigned int i = 0; i < files.size(); ++i) { char* file = (char*) files.at(i).c_str(); @@ -901,17 +902,17 @@ int twrpTar::createTar() { LOGINFO("Using encryption and compression...\n"); int i, pipes[4]; - if (pipe(pipes) < 0) { + if (pipe2(pipes, O_CLOEXEC) < 0) { LOGINFO("Error creating first pipe\n"); gui_err("backup_error=Error creating backup."); return -1; } - if (pipe(pipes + 2) < 0) { + if (pipe2(pipes + 2, O_CLOEXEC) < 0) { LOGINFO("Error creating second pipe\n"); gui_err("backup_error=Error creating backup."); return -1; } - output_fd = open(tarfn.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + output_fd = open(tarfn.c_str(), O_CLOEXEC | O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (output_fd < 0) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno))); for (i = 0; i < 4; i++) @@ -929,20 +930,11 @@ int twrpTar::createTar() { return -1; } else if (pigz_pid == 0) { // pigz Child - close(pipes[1]); - close(pipes[2]); - int stdinfd = fileno(stdin); - int stdoutfd = fileno(stdout); - close(stdinfd); - dup2(pipes[0], stdinfd); - close(stdoutfd); - dup2(pipes[3], stdoutfd); + dup2(pipes[0], STDIN_FILENO); + dup2(pipes[3], STDOUT_FILENO); if (execlp("pigz", "pigz", "-", NULL) < 0) { LOGINFO("execlp pigz ERROR!\n"); gui_err("backup_error=Error creating backup."); - close(output_fd); - close(pipes[0]); - close(pipes[3]); _exit(-1); } } else { @@ -958,20 +950,11 @@ int twrpTar::createTar() { return -1; } else if (oaes_pid == 0) { // openaes Child - close(pipes[0]); - close(pipes[1]); - close(pipes[3]); - int stdinfd = fileno(stdin); - int stdoutfd = fileno(stdout); - close(stdinfd); - dup2(pipes[2], stdinfd); - close(stdoutfd); - dup2(output_fd, stdoutfd); + dup2(pipes[2], STDIN_FILENO); + dup2(output_fd, STDOUT_FILENO); if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) { LOGINFO("execlp openaes ERROR!\n"); gui_err("backup_error=Error creating backup."); - close(pipes[2]); - close(output_fd); _exit(-1); } } else { @@ -982,7 +965,7 @@ int twrpTar::createTar() { fd = pipes[1]; init_libtar_no_buffer(progress_pipe_fd); tar_type.writefunc = write_tar_no_buffer; - if (tar_fdopen(&t, fd, charRootDir, &tar_type, O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { + if (tar_fdopen(&t, fd, charRootDir, &tar_type, O_CLOEXEC | O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { close(fd); LOGINFO("tar_fdopen failed\n"); gui_err("backup_error=Error creating backup."); @@ -1001,15 +984,14 @@ int twrpTar::createTar() { output_fd = open(TW_ADB_BACKUP, O_WRONLY); } else { - output_fd = open(tarfn.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + output_fd = open(tarfn.c_str(), O_CLOEXEC | O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); } if (output_fd < 0) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno))); - close(pigzfd[0]); return -1; } - if (pipe(pigzfd) < 0) { + if (pipe2(pigzfd, O_CLOEXEC) < 0) { LOGINFO("Error creating pipe\n"); gui_err("backup_error=Error creating backup."); close(output_fd); @@ -1026,14 +1008,11 @@ int twrpTar::createTar() { return -1; } else if (pigz_pid == 0) { // Child - close(pigzfd[1]); // close unused output pipe - dup2(pigzfd[0], fileno(stdin)); // remap stdin - dup2(output_fd, fileno(stdout)); // remap stdout to output file + dup2(pigzfd[0], STDIN_FILENO); // remap stdin + dup2(output_fd, STDOUT_FILENO); // remap stdout to output file if (execlp("pigz", "pigz", "-", NULL) < 0) { LOGINFO("execlp pigz ERROR!\n"); gui_err("backup_error=Error creating backup."); - close(output_fd); - close(pigzfd[0]); _exit(-1); } } else { @@ -1042,7 +1021,7 @@ int twrpTar::createTar() { fd = pigzfd[1]; // copy parent output init_libtar_no_buffer(progress_pipe_fd); tar_type.writefunc = write_tar_no_buffer; - if (tar_fdopen(&t, fd, charRootDir, &tar_type, O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { + if (tar_fdopen(&t, fd, charRootDir, &tar_type, O_CLOEXEC | O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { close(fd); LOGINFO("tar_fdopen failed\n"); gui_err("backup_error=Error creating backup."); @@ -1054,12 +1033,12 @@ int twrpTar::createTar() { current_archive_type = ENCRYPTED; LOGINFO("Using encryption...\n"); int oaesfd[2]; - output_fd = open(tarfn.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + output_fd = open(tarfn.c_str(), O_CLOEXEC | O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (output_fd < 0) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno))); return -1; } - if (pipe(oaesfd) < 0) { + if (pipe2(oaesfd, O_CLOEXEC) < 0) { LOGINFO("Error creating pipe\n"); gui_err("backup_error=Error creating backup."); close(output_fd); @@ -1076,14 +1055,11 @@ int twrpTar::createTar() { return -1; } else if (oaes_pid == 0) { // Child - close(oaesfd[1]); // close unused - dup2(oaesfd[0], fileno(stdin)); // remap stdin - dup2(output_fd, fileno(stdout)); // remap stdout to output file + dup2(oaesfd[0], STDIN_FILENO); // remap stdin + dup2(output_fd, STDOUT_FILENO); // remap stdout to output file if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) { LOGINFO("execlp openaes ERROR!\n"); gui_err("backup_error=Error creating backup."); - close(output_fd); - close(oaesfd[0]); _exit(-1); } } else { @@ -1092,7 +1068,7 @@ int twrpTar::createTar() { fd = oaesfd[1]; // copy parent output init_libtar_no_buffer(progress_pipe_fd); tar_type.writefunc = write_tar_no_buffer; - if (tar_fdopen(&t, fd, charRootDir, &tar_type, O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { + if (tar_fdopen(&t, fd, charRootDir, &tar_type, O_CLOEXEC | O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { close(fd); LOGINFO("tar_fdopen failed\n"); gui_err("backup_error=Error creating backup."); @@ -1108,7 +1084,7 @@ int twrpTar::createTar() { LOGINFO("Opening TW_ADB_BACKUP uncompressed stream\n"); tar_type.writefunc = write_tar_no_buffer; output_fd = open(TW_ADB_BACKUP, O_WRONLY); - if(tar_fdopen(&t, output_fd, charRootDir, &tar_type, O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { + if(tar_fdopen(&t, output_fd, charRootDir, &tar_type, O_CLOEXEC | O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { close(output_fd); LOGERR("tar_fdopen failed\n"); return -1; @@ -1116,7 +1092,7 @@ int twrpTar::createTar() { } else { tar_type.writefunc = write_tar; - if (tar_open(&t, charTarFile, &tar_type, O_WRONLY | O_CREAT | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) == -1) { + if (tar_open(&t, charTarFile, &tar_type, O_CLOEXEC | O_WRONLY | O_CREAT | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) == -1) { LOGERR("tar_open error opening '%s'\n", tarfn.c_str()); gui_err("backup_error=Error creating backup."); return -1; @@ -1134,19 +1110,19 @@ int twrpTar::openTar() { if (current_archive_type == COMPRESSED_ENCRYPTED) { LOGINFO("Opening encrypted and compressed backup...\n"); int i, pipes[4]; - input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE); + input_fd = open(tarfn.c_str(), O_CLOEXEC | O_RDONLY | O_LARGEFILE); if (input_fd < 0) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno))); return -1; } - if (pipe(pipes) < 0) { + if (pipe2(pipes, O_CLOEXEC) < 0) { LOGINFO("Error creating first pipe\n"); gui_err("restore_error=Error during restore process."); close(input_fd); return -1; } - if (pipe(pipes + 2) < 0) { + if (pipe2(pipes + 2, O_CLOEXEC) < 0) { LOGINFO("Error creating second pipe\n"); gui_err("restore_error=Error during restore process."); close(pipes[0]); @@ -1165,20 +1141,11 @@ int twrpTar::openTar() { return -1; } else if (oaes_pid == 0) { // openaes Child - close(pipes[0]); // Close pipes that are not used by this child - close(pipes[2]); - close(pipes[3]); - int stdinfd = fileno(stdin); - int stdoutfd = fileno(stdout); - close(stdinfd); - dup2(input_fd, stdinfd); - close(stdoutfd); - dup2(pipes[1], stdoutfd); + dup2(input_fd, STDIN_FILENO); + dup2(pipes[1], STDOUT_FILENO); if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) { LOGINFO("execlp openaes ERROR!\n"); gui_err("restore_error=Error during restore process."); - close(input_fd); - close(pipes[1]); _exit(-1); } } else { @@ -1194,20 +1161,11 @@ int twrpTar::openTar() { return -1; } else if (pigz_pid == 0) { // pigz Child - close(pipes[1]); // Close pipes not used by this child - close(pipes[2]); - int stdinfd = fileno(stdin); - int stdoutfd = fileno(stdout); - close(stdinfd); - dup2(pipes[0], stdinfd); - close(stdoutfd); - dup2(pipes[3], stdoutfd); + dup2(pipes[0], STDIN_FILENO); + dup2(pipes[3], STDOUT_FILENO); if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) { LOGINFO("execlp pigz ERROR!\n"); gui_err("restore_error=Error during restore process."); - close(input_fd); - close(pipes[0]); - close(pipes[3]); _exit(-1); } } else { @@ -1216,7 +1174,7 @@ int twrpTar::openTar() { close(pipes[1]); close(pipes[3]); fd = pipes[2]; - if (tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { + if (tar_fdopen(&t, fd, charRootDir, NULL, O_CLOEXEC | O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { close(fd); LOGINFO("tar_fdopen failed\n"); gui_err("restore_error=Error during restore process."); @@ -1227,13 +1185,13 @@ int twrpTar::openTar() { } else if (current_archive_type == ENCRYPTED) { LOGINFO("Opening encrypted backup...\n"); int oaesfd[2]; - input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE); + input_fd = open(tarfn.c_str(), O_CLOEXEC | O_RDONLY | O_LARGEFILE); if (input_fd < 0) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno))); return -1; } - if (pipe(oaesfd) < 0) { + if (pipe2(oaesfd, O_CLOEXEC) < 0) { LOGINFO("Error creating pipe\n"); gui_err("restore_error=Error during restore process."); close(input_fd); @@ -1250,23 +1208,18 @@ int twrpTar::openTar() { return -1; } else if (oaes_pid == 0) { // Child - close(oaesfd[0]); // Close unused pipe - int stdinfd = fileno(stdin); - close(stdinfd); // close stdin - dup2(oaesfd[1], fileno(stdout)); // remap stdout - dup2(input_fd, stdinfd); // remap input fd to stdin + dup2(oaesfd[1], STDOUT_FILENO); // remap stdout + dup2(input_fd, STDIN_FILENO); // remap input fd to stdin if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) { LOGINFO("execlp openaes ERROR!\n"); gui_err("restore_error=Error during restore process."); - close(input_fd); - close(oaesfd[1]); _exit(-1); } } else { // Parent close(oaesfd[1]); // close parent output fd = oaesfd[0]; // copy parent input - if (tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { + if (tar_fdopen(&t, fd, charRootDir, NULL, O_CLOEXEC | O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { close(fd); LOGINFO("tar_fdopen failed\n"); gui_err("restore_error=Error during restore process."); @@ -1279,17 +1232,17 @@ int twrpTar::openTar() { LOGINFO("Opening gzip compressed tar...\n"); if (part_settings->adbbackup) { LOGINFO("opening TW_ADB_RESTORE compressed stream\n"); - input_fd = open(TW_ADB_RESTORE, O_RDONLY | O_LARGEFILE); + input_fd = open(TW_ADB_RESTORE, O_CLOEXEC | O_RDONLY | O_LARGEFILE); } else - input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE); + input_fd = open(tarfn.c_str(), O_CLOEXEC | O_RDONLY | O_LARGEFILE); if (input_fd < 0) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno))); return -1; } - if (pipe(pigzfd) < 0) { + if (pipe2(pigzfd, O_CLOEXEC) < 0) { LOGINFO("Error creating pipe\n"); gui_err("restore_error=Error during restore process."); close(input_fd); @@ -1306,13 +1259,10 @@ int twrpTar::openTar() { return -1; } else if (pigz_pid == 0) { // Child - close(pigzfd[0]); - dup2(pigzfd[1], fileno(stdout)); // remap stdout - dup2(input_fd, fileno(stdin)); // remap input fd to stdin + dup2(pigzfd[1], STDOUT_FILENO); // remap stdout + dup2(input_fd, STDIN_FILENO); // remap input fd to stdin if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) { - close(pigzfd[1]); - close(input_fd); - LOGINFO("execlp openaes ERROR!\n"); + LOGINFO("execlp pigz ERROR!\n"); gui_err("restore_error=Error during restore process."); _exit(-1); } @@ -1320,7 +1270,7 @@ int twrpTar::openTar() { // Parent close(pigzfd[1]); // close parent output fd = pigzfd[0]; // copy parent input - if (tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { + if (tar_fdopen(&t, fd, charRootDir, NULL, O_CLOEXEC | O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { close(fd); LOGINFO("tar_fdopen failed\n"); gui_err("restore_error=Error during restore process."); @@ -1331,14 +1281,14 @@ int twrpTar::openTar() { if (part_settings->adbbackup) { LOGINFO("Opening TW_ADB_RESTORE uncompressed stream\n"); input_fd = open(TW_ADB_RESTORE, O_RDONLY); - if (tar_fdopen(&t, input_fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { + if (tar_fdopen(&t, input_fd, charRootDir, NULL, O_CLOEXEC | O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { LOGERR("Unable to open tar archive '%s'\n", charTarFile); gui_err("restore_error=Error during restore process."); return -1; } } else { - if (tar_open(&t, charTarFile, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { + if (tar_open(&t, charTarFile, NULL, O_CLOEXEC | O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) { LOGERR("Unable to open tar archive '%s'\n", charTarFile); gui_err("restore_error=Error during restore process."); return -1; @@ -1395,7 +1345,6 @@ int twrpTar::closeTar() { return -1; } if (current_archive_type > 0) { - close(fd); int status; if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0) return -1; @@ -1522,7 +1471,7 @@ unsigned long long twrpTar::uncompressedSize(string filename) { Command = "pigz -l '" + filename + "'"; /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '"; we get the uncompressed size at once. */ - TWFunc::Exec_Cmd(Command, result); + TWFunc::Exec_Cmd(Command, result, false); if (!result.empty()) { /* Expected output: compressed original reduced name @@ -1547,7 +1496,7 @@ unsigned long long twrpTar::uncompressedSize(string filename) { Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l"; /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '"; we get the uncompressed size at once. */ - TWFunc::Exec_Cmd(Command, result); + TWFunc::Exec_Cmd(Command, result, false); if (!result.empty()) { LOGINFO("result was: '%s'\n", result.c_str()); /* Expected output: diff --git a/updater/install.cpp b/updater/install.cpp index 2266127f25..bcc859a1e2 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -149,94 +149,6 @@ Value* UIPrintFn(const char* name, State* state, const std::vector>& argv) { - if (argv.size() < 1 || argv.size() > 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %zu", name, - argv.size()); - } - - if (argv.size() == 2) { - // The two-argument version extracts to a file. - - std::vector args; - if (!ReadArgs(state, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name, - argv.size()); - } - const std::string& zip_path = args[0]; - const std::string& dest_path = args[1]; - - ZipArchiveHandle za = static_cast(state->cookie)->package_zip; - ZipString zip_string_path(zip_path.c_str()); - ZipEntry entry; - if (FindEntry(za, zip_string_path, &entry) != 0) { - LOG(ERROR) << name << ": no " << zip_path << " in package"; - return StringValue(""); - } - - unique_fd fd(TEMP_FAILURE_RETRY( - ota_open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR))); - if (fd == -1) { - PLOG(ERROR) << name << ": can't open " << dest_path << " for write"; - return StringValue(""); - } - - bool success = true; - int32_t ret = ExtractEntryToFile(za, &entry, fd); - if (ret != 0) { - LOG(ERROR) << name << ": Failed to extract entry \"" << zip_path << "\" (" - << entry.uncompressed_length << " bytes) to \"" << dest_path - << "\": " << ErrorCodeString(ret); - success = false; - } - if (ota_fsync(fd) == -1) { - PLOG(ERROR) << "fsync of \"" << dest_path << "\" failed"; - success = false; - } - if (ota_close(fd) == -1) { - PLOG(ERROR) << "close of \"" << dest_path << "\" failed"; - success = false; - } - - return StringValue(success ? "t" : ""); - } else { - // The one-argument version returns the contents of the file as the result. - - std::vector args; - if (!ReadArgs(state, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name, - argv.size()); - } - const std::string& zip_path = args[0]; - - ZipArchiveHandle za = static_cast(state->cookie)->package_zip; - ZipString zip_string_path(zip_path.c_str()); - ZipEntry entry; - if (FindEntry(za, zip_string_path, &entry) != 0) { - return ErrorAbort(state, kPackageExtractFileFailure, "%s(): no %s in package", name, - zip_path.c_str()); - } - - std::string buffer; - buffer.resize(entry.uncompressed_length); - - int32_t ret = - ExtractToMemory(za, &entry, reinterpret_cast(&buffer[0]), buffer.size()); - if (ret != 0) { - return ErrorAbort(state, kPackageExtractFileFailure, - "%s: Failed to extract entry \"%s\" (%zu bytes) to memory: %s", name, - zip_path.c_str(), buffer.size(), ErrorCodeString(ret)); - } - - return new Value(VAL_BLOB, buffer); - } -} - // apply_patch(src_file, tgt_file, tgt_sha1, tgt_size, patch1_sha1, patch1_blob, [...]) // Applies a binary patch to the src_file to produce the tgt_file. If the desired target is the // same as the source, pass "-" for tgt_file. tgt_sha1 and tgt_size are the expected final SHA1 diff --git a/variables.h b/variables.h index 76da715dab..330ffdabb2 100644 --- a/variables.h +++ b/variables.h @@ -17,9 +17,11 @@ #ifndef _VARIABLES_HEADER_ #define _VARIABLES_HEADER_ -#define TW_MAIN_VERSION_STR "3.3.1" +#define TW_MAIN_VERSION_STR "3.6.1_9" #define TW_VERSION_STR TW_MAIN_VERSION_STR TW_DEVICE_VERSION - +#define TW_SETTINGS_FILE ".twrps" +#define TW_RECOVERY_NAME "TWRP" +#define TW_DEFAULT_RECOVERY_FOLDER "/" TW_RECOVERY_NAME #define TW_USE_COMPRESSION_VAR "tw_use_compression" #define TW_FILENAME "tw_filename" #define TW_ZIP_INDEX "tw_zip_index" @@ -72,12 +74,14 @@ #define TW_FORCE_DIGEST_CHECK_VAR "tw_force_digest_check" #define TW_SKIP_DIGEST_CHECK_VAR "tw_skip_digest_check" #define TW_SKIP_DIGEST_GENERATE_VAR "tw_skip_digest_generate" +#define TW_SKIP_DIGEST_CHECK_ZIP_VAR "tw_skip_digest_check_zip" #define TW_SIGNED_ZIP_VERIFY_VAR "tw_signed_zip_verify" #define TW_INSTALL_REBOOT_VAR "tw_install_reboot" #define TW_TIME_ZONE_VAR "tw_time_zone" #define TW_RM_RF_VAR "tw_rm_rf" #define TW_BACKUPS_FOLDER_VAR "tw_backups_folder" +#define TW_RECOVERY_FOLDER_VAR "tw_recovery_folder" #define TW_SDEXT_SIZE "tw_sdext_size" #define TW_SWAP_SIZE "tw_swap_size" @@ -96,6 +100,7 @@ #define TW_REBOOT_RECOVERY "tw_reboot_recovery" #define TW_REBOOT_POWEROFF "tw_reboot_poweroff" #define TW_REBOOT_BOOTLOADER "tw_reboot_bootloader" +#define TW_REBOOT_HACKED_BL "tw_reboot_hacked_bl" #define TW_USE_EXTERNAL_STORAGE "tw_use_external_storage" #define TW_HAS_INTERNAL "tw_has_internal" @@ -140,6 +145,14 @@ #define TW_MILITARY_TIME "tw_military_time" #define TW_USE_SHA2 "tw_use_sha2" #define TW_NO_SHA2 "tw_no_sha2" +#define TW_UNMOUNT_SYSTEM "tw_unmount_system" +#define TW_AUTO_REFLASHTWRP_VAR "tw_auto_reflashtwrp" + +// Theme versioning +// version 2 requires theme to handle power button as action togglebacklight +// version 4 adds listbox support to reboot page +// version 5 adds File Manager options, nano & Flash Current TWRP +#define TW_THEME_VERSION 5 // Also used: // tw_boot_is_mountable