diff --git a/source/ApplicationState.cpp b/source/ApplicationState.cpp index a0f2843..fbb2cf4 100644 --- a/source/ApplicationState.cpp +++ b/source/ApplicationState.cpp @@ -1,7 +1,12 @@ #include "ApplicationState.h" #include "WiiUScreen.h" #include "ScreenUtils.h" +#include "../build/safe_rpx.h" +#include "../build/safe_payload.h" #include +#include + +extern "C" void OSForceFullRelaunch(); void ApplicationState::render() { WiiUScreen::clearScreen(); @@ -108,6 +113,10 @@ void ApplicationState::render() { WiiUScreen::drawLine("... patching system.xml"); } else if (this->state == STATE_INSTALL_RPX) { WiiUScreen::drawLine("... install safe.rpx"); + } else if (this->state == STATE_INSTALL_SUCCESS) { + WiiUScreen::drawLine("Aroma was successfully installed"); + WiiUScreen::drawLine(); + WiiUScreen::drawLine("Press A to reboot the console"); } printFooter(); WiiUScreen::flipBuffers(); @@ -115,6 +124,7 @@ void ApplicationState::render() { void ApplicationState::update(Input *input) { if (this->state == STATE_ERROR) { + OSEnableHomeButtonMenu(true); if (entrySelected(input)) { SYSLaunchMenu(); } @@ -186,24 +196,52 @@ void ApplicationState::update(Input *input) { } else if (this->state == STATE_INSTALL_FST) { auto result = InstallerService::patchFST(this->appInfo->path, this->appInfo->fstHash); if (result != InstallerService::SUCCESS) { - this->error = ERROR_INSTALLER_ERROR; + setError(ERROR_INSTALLER_ERROR); this->installerError = result; - this->state = STATE_ERROR; } else { this->state = STATE_INSTALL_COS; } } else if (this->state == STATE_INSTALL_COS) { auto result = InstallerService::patchCOS(this->appInfo->path, this->appInfo->cosHash); if (result != InstallerService::SUCCESS) { - this->error = ERROR_INSTALLER_ERROR; + setError(ERROR_INSTALLER_ERROR); this->installerError = result; - this->state = STATE_ERROR; } else { this->state = STATE_INSTALL_RPX; } } else if (this->state == STATE_INSTALL_RPX) { + auto result = InstallerService::copyRPX(this->appInfo->path, safe_rpx, safe_rpx_size, RPX_HASH); + if (result != InstallerService::SUCCESS) { + setError(ERROR_INSTALLER_ERROR); + this->installerError = result; + } else { + if (this->installColdboot) { + this->state = STATE_INSTALL_SYSTEM_XML; + } else { + this->state = STATE_INSTALL_SUCCESS; + } + } + } else if (this->state == STATE_INSTALL_SYSTEM_XML) { + auto result = InstallerService::patchSystemXML("storage_slc_installer:/config", this->appInfo->titleId); + if (result != InstallerService::SUCCESS) { + setError(ERROR_INSTALLER_ERROR); + this->installerError = result; + } else { + auto fsaFd = IOSUHAX_FSA_Open(); + if (fsaFd >= 0) { + if (IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/storage_mlc01") == 0) { + DEBUG_FUNCTION_LINE("Flushed mlc"); + } + IOSUHAX_FSA_Close(fsaFd); + } else { + DEBUG_FUNCTION_LINE("Failed to open fsa"); + } + this->state = STATE_INSTALL_SUCCESS; + } + } else if (this->state == STATE_INSTALL_SUCCESS) { if (entrySelected(input)) { - this->state = STATE_WELCOME_SCREEN; + OSForceFullRelaunch(); + SYSLaunchMenu(); } } } @@ -280,9 +318,10 @@ std::string ApplicationState::ErrorDescription() { return "UNKNOWN_ERROR"; } -void ApplicationState::setError(eErrorState error) { +void ApplicationState::setError(eErrorState err) { this->state = STATE_ERROR; - this->error = error; + this->error = err; + OSEnableHomeButtonMenu(true); } void ApplicationState::handleError() { diff --git a/source/ApplicationState.h b/source/ApplicationState.h index 1d38621..9014a0d 100644 --- a/source/ApplicationState.h +++ b/source/ApplicationState.h @@ -26,9 +26,10 @@ public: STATE_INSTALL_CONFIRM_DIALOG, STATE_INSTALL_STARTED, STATE_INSTALL_FST, - STATE_INSTALL_SYSTEM_XML, STATE_INSTALL_COS, - STATE_INSTALL_RPX + STATE_INSTALL_RPX, + STATE_INSTALL_SYSTEM_XML, + STATE_INSTALL_SUCCESS }; ApplicationState(); @@ -57,7 +58,7 @@ public: void proccessMenuNavigation(Input *input, int maxOptionValue); - bool entrySelected(Input *input); + static bool entrySelected(Input *input); bool installColdboot = false; InstallerService::eResults installerError = InstallerService::eResults::SUCCESS; diff --git a/source/InstallerService.cpp b/source/InstallerService.cpp index 5d84bda..ad27f95 100644 --- a/source/InstallerService.cpp +++ b/source/InstallerService.cpp @@ -15,21 +15,20 @@ #include systemXMLInformation systemXMLHashInformation[] = { - {WII_U_MENU_JAP, 0x0005001010040000, "2645065A42D18D390C78543E3C4FE7E1D1957A63"}, - {WII_U_MENU_USA, 0x0005001010040100, "124562D41A02C7112DDD5F9A8F0EE5DF97E23471"}, - {WII_U_MENU_EUR, 0x0005001010040200, "F06041A4E5B3F899E748F1BAEB524DE058809F1D"}, - {HEALTH_SAFETY_JAP, 0x000500101004E000, "066D672824128713F0A7D156142A68B998080148"}, - {HEALTH_SAFETY_USA, 0x000500101004E100, "0EBCA1DFC0AB7A6A7FE8FB5EAF23179621B726A1"}, - {HEALTH_SAFETY_EUR, 0x000500101004E200, "DE46EC3E9B823ABA6CB0638D0C4CDEEF9C793BDD"} + {WII_U_MENU_JAP, 0x0005001010040000L, "2645065A42D18D390C78543E3C4FE7E1D1957A63"}, + {WII_U_MENU_USA, 0x0005001010040100L, "124562D41A02C7112DDD5F9A8F0EE5DF97E23471"}, + {WII_U_MENU_EUR, 0x0005001010040200L, "F06041A4E5B3F899E748F1BAEB524DE058809F1D"}, + {HEALTH_SAFETY_JAP, 0x000500101004E000L, "066D672824128713F0A7D156142A68B998080148"}, + {HEALTH_SAFETY_USA, 0x000500101004E100L, "0EBCA1DFC0AB7A6A7FE8FB5EAF23179621B726A1"}, + {HEALTH_SAFETY_EUR, 0x000500101004E200L, "DE46EC3E9B823ABA6CB0638D0C4CDEEF9C793BDD"} }; appInformation supportedApps[] = { - {0x000500101004E000, "Health and Safety Information [JPN]", false, {'\0'}, "9D34DDD91604D781FDB0727AC75021833304964C", "0"}, - {0x000500101004E100, "Health and Safety Information [USA]", false, {'\0'}, "045734666A36C7EF0258A740855886EBDB20D59B", "0"}, - {0x000500101004E200, "Health and Safety Information [EUR]", false, {'\0'}, "130A76F8B36B36D43B88BBC74393D9AFD9CFD2A4", "F6EBF7BC8AE3AF3BB8A42E0CF3FDA051278AEB03"}, + {0x000500101004E000L, "Health and Safety Information [JPN]", false, {'\0'}, "9D34DDD91604D781FDB0727AC75021833304964C", "0"}, + {0x000500101004E100L, "Health and Safety Information [USA]", false, {'\0'}, "045734666A36C7EF0258A740855886EBDB20D59B", "0"}, + {0x000500101004E200L, "Health and Safety Information [EUR]", false, {'\0'}, "130A76F8B36B36D43B88BBC74393D9AFD9CFD2A4", "F6EBF7BC8AE3AF3BB8A42E0CF3FDA051278AEB03"}, }; - InstallerService::eResults InstallerService::checkCOS(const std::string &path, char *hash) { std::string cosFilePath = path + "/code/cos.xml"; DEBUG_FUNCTION_LINE("Loading %s", cosFilePath.c_str()); @@ -329,7 +328,7 @@ std::string InstallerService::ErrorMessage(InstallerService::eResults error) { InstallerService::eResults InstallerService::patchFST(const std::string &path, const char *fstHash) { std::string fstFilePath = path + "/code/title.fst"; std::string fstBackupFilePath = path + "/code/backup.fst"; - std::string fstTargetFilePath = path + "/code/titla.fst"; + std::string fstTargetFilePath = path + "/code/title.fst"; if (!FSUtils::copyFile(fstFilePath, fstBackupFilePath)) { DEBUG_FUNCTION_LINE("Failed to copy files"); @@ -440,3 +439,123 @@ InstallerService::eResults InstallerService::patchCOS(const std::string &path, c return COS_XML_HASH_MISMATCH; } + + +InstallerService::eResults InstallerService::copyRPX(const std::string &path, const uint8_t *rpx_data, size_t size, const std::string &rpx_hash) { + std::string rpxSourceFilePath = path + "/code/safe.rpx"; + std::string rpxBackupFilePath = path + "/code/sbac.rpx"; + std::string rpxTargetFilePath = path + "/code/safe.rpx"; + + if (!FSUtils::copyFile(rpxSourceFilePath, rpxBackupFilePath)) { + DEBUG_CONSOLE_LOG("Failed to copy files"); + return FAILED_TO_COPY_FILES; + } + + std::string srcHash = Utils::hashFile(rpxSourceFilePath); + std::string dstHash = Utils::hashFile(rpxBackupFilePath); + + if (srcHash != dstHash) { + ::remove(rpxBackupFilePath.c_str()); + DEBUG_CONSOLE_LOG("Hashes do not match. %s %s", srcHash.c_str(), dstHash.c_str()); + return FAILED_TO_CHECK_HASH_COPIED_FILES; + } + + if (FSUtils::saveBufferToFile(rpxTargetFilePath.c_str(), (void *) rpx_data, size) < 0) { + DEBUG_CONSOLE_LOG("Cannot save rpx to file %s", rpxTargetFilePath.c_str()); + return SUCCESS; + } + + std::string newHash = Utils::hashFile(rpxTargetFilePath); + + if (StringTools::strCompareIC(rpx_hash, newHash)) { + ::remove(rpxBackupFilePath.c_str()); + DEBUG_CONSOLE_LOG("Successfully patched the safe.rpx"); + return SUCCESS; + } else { + DEBUG_CONSOLE_LOG("Hash mismatch! Expected %s but got %s while patching safe.rpx", rpx_hash.c_str(), newHash.c_str()); + } + + FSUtils::copyFile(rpxBackupFilePath, rpxTargetFilePath); + + std::string srcHash2 = Utils::hashFile(rpxTargetFilePath); + + if (srcHash != srcHash2) { + DEBUG_CONSOLE_LOG("Something went wrong. Failed to restore the safe.rpx. DO NOT RESTART THE SYSTEM until you manually restored the safe.rpx"); + return RPX_HASH_MISMATCH_RESTORE_FAILED; + } + ::remove(rpxBackupFilePath.c_str()); + + return RPX_HASH_MISMATCH; +} + +InstallerService::eResults InstallerService::patchSystemXML(const std::string &path, uint64_t titleId) { + std::string inputFile = std::string(path + "/system.xml"); + std::string backupFile = std::string(path + "/sbackup.xml"); + std::string finalFile = std::string(path + "/system.xml"); + + if (!FSUtils::copyFile(inputFile, backupFile)) { + DEBUG_CONSOLE_LOG("Failed to copy files"); + return FAILED_TO_COPY_FILES; + } + + std::string srcHash = Utils::hashFile(inputFile); + std::string dstHash = Utils::hashFile(backupFile); + + if (srcHash != dstHash) { + ::remove(backupFile.c_str()); + DEBUG_CONSOLE_LOG("Hashes do not match. %s %s", srcHash.c_str(), dstHash.c_str()); + return FAILED_TO_CHECK_HASH_COPIED_FILES; + } + + systemXMLInformation *data = nullptr; + int arrayLength = (sizeof(systemXMLHashInformation) / sizeof(*systemXMLHashInformation)); + for (int i = 0; i < arrayLength; i++) { + if (systemXMLHashInformation[i].titleId == titleId) { + data = &systemXMLHashInformation[i]; + break; + } + } + + if (data == nullptr) { + ::remove(backupFile.c_str()); + DEBUG_FUNCTION_LINE("Data was NULL"); + return SYSTEM_XML_INFORMATION_NOT_FOUND; + } + + pugi::xml_document doc; + pugi::xml_parse_result resultSystem = doc.load_file(inputFile.c_str()); + if (!resultSystem) { + ::remove(backupFile.c_str()); + DEBUG_FUNCTION_LINE("Error while parsing %s: %s", inputFile.c_str(), resultSystem.description()); + return SYSTEM_XML_PARSING_FAILED; + } + + char tmp[18]; + snprintf(tmp, 17, "%016llX", data->titleId); + + doc.child("system").child("default_title_id").first_child().set_value(tmp); + doc.save_file(finalFile.c_str(), " ", pugi::format_default, pugi::encoding_utf8); + + std::string newHash = Utils::hashFile(finalFile); + + if (std::string(data->hash) == newHash) { + ::remove(backupFile.c_str()); + DEBUG_FUNCTION_LINE("Successfully patched the system.xml"); + return SUCCESS; + } else { + DEBUG_FUNCTION_LINE("Hash mismatch! Expected %s but got %s while setting default titleID to %s", data->hash, newHash.c_str(), data->titleId); + } + + FSUtils::copyFile(backupFile, finalFile); + + std::string srcHash2 = Utils::hashFile(finalFile); + + if (srcHash != srcHash2) { + DEBUG_FUNCTION_LINE("Something went wrong. Failed to restore the system.xml. DO NOT RESTART THE SYSTEM until you manually restored the system.xml"); + return SYSTEM_XML_HASH_MISMATCH_RESTORE_FAILED; + } + + ::remove(backupFile.c_str()); + + return SYSTEM_XML_HASH_MISMATCH; +} diff --git a/source/InstallerService.h b/source/InstallerService.h index 9166452..1218d05 100644 --- a/source/InstallerService.h +++ b/source/InstallerService.h @@ -43,6 +43,10 @@ public: static eResults patchFST(const std::string &path, const char *hash); + static eResults copyRPX(const std::string &path, const uint8_t *rpx_data, size_t size, const std::string &rpx_hash); + + + static eResults patchSystemXML(const std::string &path, uint64_t id); private: static eResults patchFSTData(uint8_t *fstData, uint32_t size); diff --git a/source/main.cpp b/source/main.cpp index cb41645..88d329b 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -10,7 +10,6 @@ #include #include #include "WiiUScreen.h" -#include "utils/logger.h" #include "InstallerService.h" #include "../build/safe_payload.h"