From 66a1949df91cc558bf5573c395fa9084c1365e81 Mon Sep 17 00:00:00 2001 From: Ethan Yonker Date: Thu, 10 Dec 2015 10:19:45 -0600 Subject: Adopted Storage support -Detects, decrypts, and mounts an adopted SD card if a secondary block device is defined (usually mmcblk1) -Handles unified storage -Displays the adopted storage in MTP along with internal -Factory Reset - wiped just like a data media device, we retain the keys folder and the storage.xml during a factory reset -Backup / Restore -Disable mass storage when adopted storage is present -Read storage nickname from storage.xml and apply it to display names in the GUI -Read storage.xml and determine what storage location is in use for /sdcard and remap accordingly libgpt_twrp is source code mostly kanged from an efimanager project. It is GPL v2 or higher, so we will opt for GPL v3. Change-Id: Ieda0030bec5155ba8d2b9167dc0016cebbf39d55 --- partitionmanager.cpp | 132 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 12 deletions(-) (limited to 'partitionmanager.cpp') diff --git a/partitionmanager.cpp b/partitionmanager.cpp index 00c4f8fdd..81d448dc6 100644 --- a/partitionmanager.cpp +++ b/partitionmanager.cpp @@ -57,6 +57,8 @@ extern "C" { #ifdef TW_INCLUDE_CRYPTO #include "crypto/lollipop/cryptfs.h" + #include "gui/rapidxml.hpp" + #include "gui/pages.hpp" #endif extern bool datamedia; @@ -167,6 +169,9 @@ int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error) DataManager::SetValue("TW_CRYPTO_TYPE", password_type); } } + if (Decrypt_Data && (!Decrypt_Data->Is_Encrypted || Decrypt_Data->Is_Decrypted) && Decrypt_Data->Mount(false)) { + Decrypt_Adopted(); + } #endif Update_System_Details(); UnMount_Main_Partitions(); @@ -276,6 +281,8 @@ void TWPartitionManager::Output_Partition(TWPartition* Part) { printf("Mount_To_Decrypt "); if (Part->Can_Flash_Img) printf("Can_Flash_Img "); + if (Part->Is_Adopted_Storage) + printf("Is_Adopted_Storage "); printf("\n"); if (!Part->SubPartition_Of.empty()) printf(" SubPartition_Of: %s\n", Part->SubPartition_Of.c_str()); @@ -1504,13 +1511,13 @@ int TWPartitionManager::Fix_Permissions(void) { return result; } -TWPartition* TWPartitionManager::Find_Next_Storage(string Path, string Exclude) { +TWPartition* TWPartitionManager::Find_Next_Storage(string Path, bool Exclude_Data_Media) { std::vector::iterator iter = Partitions.begin(); if (!Path.empty()) { string Search_Path = TWFunc::Get_Root_Path(Path); for (; iter != Partitions.end(); iter++) { - if ((*iter)->Mount_Point == Search_Path) { + if (Exclude_Data_Media && (*iter)->Has_Data_Media) { iter++; break; } @@ -1518,7 +1525,9 @@ TWPartition* TWPartitionManager::Find_Next_Storage(string Path, string Exclude) } for (; iter != Partitions.end(); iter++) { - if ((*iter)->Is_Storage && (*iter)->Is_Present && (*iter)->Mount_Point != Exclude) { + if (Exclude_Data_Media && (*iter)->Has_Data_Media) { + // do nothing, do not return this type of partition + } else if ((*iter)->Is_Storage && (*iter)->Is_Present) { return (*iter); } } @@ -1563,7 +1572,7 @@ int TWPartitionManager::usb_storage_enable(void) { LOGINFO("Device doesn't have multiple lun files, mount current storage\n"); sprintf(lun_file, CUSTOM_LUN_FILE, 0); if (TWFunc::Get_Root_Path(DataManager::GetCurrentStoragePath()) == "/data") { - TWPartition* Mount = Find_Next_Storage("", "/data"); + TWPartition* Mount = Find_Next_Storage("", true); if (Mount) { if (!Open_Lun_File(Mount->Mount_Point, lun_file)) { goto error_handle; @@ -1580,13 +1589,13 @@ int TWPartitionManager::usb_storage_enable(void) { TWPartition* Mount1; TWPartition* Mount2; sprintf(lun_file, CUSTOM_LUN_FILE, 0); - Mount1 = Find_Next_Storage("", "/data"); + Mount1 = Find_Next_Storage("", true); if (Mount1) { if (!Open_Lun_File(Mount1->Mount_Point, lun_file)) { goto error_handle; } sprintf(lun_file, CUSTOM_LUN_FILE, 1); - Mount2 = Find_Next_Storage(Mount1->Mount_Point, "/data"); + Mount2 = Find_Next_Storage(Mount1->Mount_Point, true); if (Mount2) { Open_Lun_File(Mount2->Mount_Point, lun_file); } @@ -1668,6 +1677,9 @@ int TWPartitionManager::Partition_SDCard(void) { // Locate and validate device to partition TWPartition* SDCard = Find_Partition_By_Path(DataManager::GetCurrentStoragePath()); + if (SDCard->Is_Adopted_Storage) + SDCard->Revert_Adopted(); + if (SDCard == NULL || !SDCard->Removable || SDCard->Has_Data_Media) { gui_err("partition_sd_locate=Unable to locate device to partition."); return false; @@ -2263,22 +2275,35 @@ bool TWPartitionManager::Flash_Image(string Filename) { void TWPartitionManager::Translate_Partition(const char* path, const char* resource_name, const char* default_value) { TWPartition* part = PartitionManager.Find_Partition_By_Path(path); if (part) { - part->Display_Name = gui_lookup(resource_name, default_value); - part->Backup_Display_Name = part->Display_Name; + if (part->Is_Adopted_Storage) { + part->Display_Name = part->Display_Name + " - " + gui_lookup("data", "Data"); + part->Backup_Display_Name = part->Display_Name; + part->Storage_Name = part->Storage_Name + " - " + gui_lookup("adopted_storage", "Adopted Storage"); + } else { + part->Display_Name = gui_lookup(resource_name, default_value); + part->Backup_Display_Name = part->Display_Name; + } } } void TWPartitionManager::Translate_Partition(const char* path, const char* resource_name, const char* default_value, const char* storage_resource_name, const char* storage_default_value) { TWPartition* part = PartitionManager.Find_Partition_By_Path(path); if (part) { - part->Display_Name = gui_lookup(resource_name, default_value); - part->Backup_Display_Name = part->Display_Name; - if (part->Is_Storage) - part->Storage_Name = gui_lookup(storage_resource_name, storage_default_value); + if (part->Is_Adopted_Storage) { + part->Display_Name = part->Display_Name + " - " + gui_lookup("data", "Data"); + part->Backup_Display_Name = part->Display_Name; + part->Storage_Name = part->Storage_Name + " - " + gui_lookup("adopted_storage", "Adopted Storage"); + } else { + part->Display_Name = gui_lookup(resource_name, default_value); + part->Backup_Display_Name = part->Display_Name; + if (part->Is_Storage) + part->Storage_Name = gui_lookup(storage_resource_name, storage_default_value); + } } } void TWPartitionManager::Translate_Partition_Display_Names() { + LOGINFO("Translating partition display names\n"); Translate_Partition("/system", "system", "System"); Translate_Partition("/system_image", "system_image", "System Image"); Translate_Partition("/vendor", "vendor", "Vendor"); @@ -2306,3 +2331,86 @@ void TWPartitionManager::Translate_Partition_Display_Names() { // This updates the text on all of the storage selection buttons in the GUI DataManager::SetBackupFolder(); } + +void TWPartitionManager::Decrypt_Adopted() { +#ifdef TW_INCLUDE_CRYPTO + if (!Mount_By_Path("/data", false)) { + LOGERR("Cannot decrypt adopted storage because /data will not mount\n"); + return; + } + LOGINFO("Decrypt adopted storage starting\n"); + char* xmlFile = PageManager::LoadFileToBuffer("/data/system/storage.xml", NULL); + xml_document<> *doc = NULL; + xml_node<>* volumes = NULL; + xml_node<>* volume = NULL; + string Primary_Storage_UUID = ""; + if (xmlFile != NULL) { + LOGINFO("successfully loaded storage.xml\n"); + doc = new xml_document<>(); + doc->parse<0>(xmlFile); + volumes = doc->first_node("volumes"); + if (volumes) { + xml_attribute<>* psuuid = volumes->first_attribute("primaryStorageUuid"); + if (psuuid) { + Primary_Storage_UUID = psuuid->value(); + } + } + } + std::vector::iterator adopt; + for (adopt = Partitions.begin(); adopt != Partitions.end(); adopt++) { + if ((*adopt)->Removable && (*adopt)->Is_Present) { + if ((*adopt)->Decrypt_Adopted() == 0) { + if (volumes) { + xml_node<>* volume = volumes->first_node("volume"); + while (volume) { + xml_attribute<>* guid = volume->first_attribute("partGuid"); + if (guid) { + string GUID = (*adopt)->Adopted_GUID.c_str(); + GUID.insert(8, "-"); + GUID.insert(13, "-"); + GUID.insert(18, "-"); + GUID.insert(23, "-"); + + if (strcasecmp(GUID.c_str(), guid->value()) == 0) { + xml_attribute<>* attr = volume->first_attribute("nickname"); + if (attr) { + (*adopt)->Storage_Name = attr->value(); + (*adopt)->Display_Name = (*adopt)->Storage_Name; + (*adopt)->Backup_Display_Name = (*adopt)->Storage_Name; + LOGINFO("storage name from storage.xml is '%s'\n", attr->value()); + } + attr = volume->first_attribute("fsUuid"); + if (attr && !Primary_Storage_UUID.empty() && strcmp(Primary_Storage_UUID.c_str(), attr->value()) == 0) { + TWPartition* Dat = Find_Partition_By_Path("/data"); + if (Dat) { + LOGINFO("Internal storage is found on adopted storage '%s'\n", (*adopt)->Display_Name.c_str()); + LOGINFO("Changing '%s' to point to '%s'\n", Dat->Symlink_Mount_Point.c_str(), (*adopt)->Storage_Path.c_str()); + (*adopt)->Symlink_Mount_Point = Dat->Symlink_Mount_Point; + Dat->Symlink_Mount_Point = ""; + // Toggle mounts to ensure that the symlink mount point (probably /sdcard) is mounted to the right location + Dat->UnMount(false); + Dat->Mount(false); + (*adopt)->UnMount(false); + (*adopt)->Mount(false); + Output_Partition((*adopt)); + } + } + break; + } + } + volume = volume->next_sibling("volume"); + } + } + } + } + } + if (xmlFile) { + doc->clear(); + delete doc; + free(xmlFile); + } +#else + LOGINFO("Decrypt_Adopted: no crypto support\n"); + return; +#endif +} -- cgit v1.2.3