mirror of
https://github.com/wiiu-env/PayloadLoaderInstaller.git
synced 2024-12-25 00:41:49 +01:00
Add the option to uninstall Aroma
This commit is contained in:
parent
0f3e674b9a
commit
87b68dff90
@ -34,7 +34,9 @@ void ApplicationState::render() {
|
||||
WiiUScreen::drawLine("Getting app information");
|
||||
} else if (this->state == STATE_CHECK_PATCH_POSSIBLE) {
|
||||
WiiUScreen::drawLine("Check if console can be patched.");
|
||||
} else if (this->state == STATE_CHECK_PATCH_POSSIBLE_DONE) {
|
||||
} else if (this->state == STATE_CHECK_REMOVAL_POSSIBLE) {
|
||||
WiiUScreen::drawLine("Check if Aroma can be removed.");
|
||||
} else if (this->state == STATE_INSTALL_MENU) {
|
||||
WiiUScreen::drawLinef("Compatible title:");
|
||||
WiiUScreen::drawLinef("%s", appInfo->appName);
|
||||
WiiUScreen::drawLine();
|
||||
@ -74,12 +76,24 @@ void ApplicationState::render() {
|
||||
WiiUScreen::drawLine();
|
||||
WiiUScreen::drawLine("Press A to return to the Wii U Menu");
|
||||
} else {
|
||||
std::string options = "";
|
||||
WiiUScreen::drawLine("Do you want to install Aroma?");
|
||||
WiiUScreen::drawLine("");
|
||||
if (this->selectedOption == 0) {
|
||||
WiiUScreen::drawLine("> Install Exit");
|
||||
} else if (this->selectedOption == 1) {
|
||||
WiiUScreen::drawLine(" Install > Exit");
|
||||
|
||||
if (this->removalPossible) {
|
||||
if (this->selectedOption == 0) {
|
||||
WiiUScreen::drawLine("> Exit Install Remove");
|
||||
} else if (this->selectedOption == 1) {
|
||||
WiiUScreen::drawLine(" Exit > Install Remove");
|
||||
} else if (this->selectedOption == 2) {
|
||||
WiiUScreen::drawLine(" Exit Install > Remove");
|
||||
}
|
||||
} else {
|
||||
if (this->selectedOption == 0) {
|
||||
WiiUScreen::drawLine("> Exit Install");
|
||||
} else if (this->selectedOption == 1) {
|
||||
WiiUScreen::drawLine(" Exit > Install");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (this->state == STATE_INSTALL_CHOOSE_COLDBOOT) {
|
||||
@ -104,7 +118,7 @@ void ApplicationState::render() {
|
||||
if (this->selectedOption == 0) {
|
||||
WiiUScreen::drawLine("> Back Install without Coldboot");
|
||||
} else if (this->selectedOption == 1) {
|
||||
WiiUScreen::drawLine("> Back > Install without Coldboot");
|
||||
WiiUScreen::drawLine(" Back > Install without Coldboot");
|
||||
}
|
||||
} else if (this->state == STATE_INSTALL_CONFIRM_DIALOG) {
|
||||
WiiUScreen::drawLine("Are you REALLY sure you want to install Aroma?");
|
||||
@ -143,6 +157,28 @@ void ApplicationState::render() {
|
||||
WiiUScreen::drawLine("Aroma was successfully installed");
|
||||
WiiUScreen::drawLine();
|
||||
WiiUScreen::drawLine("Press A to shutdown the console");
|
||||
} else if (this->state == STATE_REMOVE_CONFIRM_DIALOG) {
|
||||
WiiUScreen::drawLine("Are you REALLY sure you want to remove Aroma?");
|
||||
WiiUScreen::drawLine("If you have installed unsigned system");
|
||||
WiiUScreen::drawLine("applications or modified system files");
|
||||
WiiUScreen::drawLine("this could make your console unusable");
|
||||
WiiUScreen::drawLine();
|
||||
WiiUScreen::drawLine();
|
||||
if (this->selectedOption == 0) {
|
||||
WiiUScreen::drawLine("> Back Remove");
|
||||
} else if (this->selectedOption == 1) {
|
||||
WiiUScreen::drawLine(" Back > Remove");
|
||||
}
|
||||
} else if (this->state == STATE_REMOVE_STARTED) {
|
||||
WiiUScreen::drawLine("Removing...");
|
||||
} else if (this->state == STATE_REMOVE_COLDBOOT) {
|
||||
WiiUScreen::drawLine("... remove system.xml coldboot patches");
|
||||
} else if (this->state == STATE_REMOVE_AROMA) {
|
||||
WiiUScreen::drawLine("... remove Aroma application patches");
|
||||
} else if (this->state == STATE_REMOVE_SUCCESS) {
|
||||
WiiUScreen::drawLine("Aroma was successfully removed");
|
||||
WiiUScreen::drawLine();
|
||||
WiiUScreen::drawLine("Press A to shutdown the console");
|
||||
}
|
||||
printFooter();
|
||||
WiiUScreen::flipBuffers();
|
||||
@ -169,17 +205,21 @@ void ApplicationState::update(Input *input) {
|
||||
getAppInformation();
|
||||
} else if (this->state == STATE_CHECK_PATCH_POSSIBLE) {
|
||||
checkPatchPossible();
|
||||
} else if (this->state == STATE_CHECK_PATCH_POSSIBLE_DONE) {
|
||||
} else if (this->state == STATE_CHECK_REMOVAL_POSSIBLE) {
|
||||
checkRemovalPossible();
|
||||
} else if (this->state == STATE_INSTALL_MENU) {
|
||||
if (this->fstPatchPossible && this->cosPatchPossible) {
|
||||
proccessMenuNavigation(input, 2);
|
||||
proccessMenuNavigation(input, 2 + (this->removalPossible ? 1 : 0));
|
||||
if (entrySelected(input)) {
|
||||
if (this->selectedOption == 0) {
|
||||
if (this->selectedOption == 1) {
|
||||
if (systemXMLPatchPossible) {
|
||||
this->state = STATE_INSTALL_CHOOSE_COLDBOOT;
|
||||
this->installColdboot = false;
|
||||
} else {
|
||||
this->state = STATE_INSTALL_CONFIRM_DIALOG;
|
||||
}
|
||||
} else if ((this->selectedOption == 2) && this->removalPossible) {
|
||||
this->state = STATE_REMOVE_CONFIRM_DIALOG;
|
||||
} else {
|
||||
SYSLaunchMenu();
|
||||
}
|
||||
@ -202,7 +242,7 @@ void ApplicationState::update(Input *input) {
|
||||
proccessMenuNavigation(input, 3);
|
||||
if (entrySelected(input)) {
|
||||
if (this->selectedOption == 0) { // Back
|
||||
this->state = STATE_CHECK_PATCH_POSSIBLE_DONE;
|
||||
this->state = STATE_INSTALL_MENU;
|
||||
} else {
|
||||
if (selectedOption == 1) { // Install with coldboot
|
||||
this->installColdboot = true;
|
||||
@ -216,7 +256,7 @@ void ApplicationState::update(Input *input) {
|
||||
proccessMenuNavigation(input, 2);
|
||||
if (entrySelected(input)) {
|
||||
if (this->selectedOption == 0) {
|
||||
this->state = STATE_CHECK_PATCH_POSSIBLE_DONE;
|
||||
this->state = STATE_INSTALL_MENU;
|
||||
} else {
|
||||
this->state = STATE_INSTALL_CONFIRM_DIALOG;
|
||||
}
|
||||
@ -226,7 +266,7 @@ void ApplicationState::update(Input *input) {
|
||||
proccessMenuNavigation(input, 2);
|
||||
if (entrySelected(input)) {
|
||||
if (this->selectedOption == 0) {
|
||||
this->state = STATE_CHECK_PATCH_POSSIBLE_DONE;
|
||||
this->state = STATE_INSTALL_MENU;
|
||||
} else {
|
||||
this->state = STATE_INSTALL_STARTED;
|
||||
OSEnableHomeButtonMenu(false);
|
||||
@ -296,6 +336,52 @@ void ApplicationState::update(Input *input) {
|
||||
if (entrySelected(input)) {
|
||||
OSShutdown();
|
||||
}
|
||||
} else if (this->state == STATE_REMOVE_CONFIRM_DIALOG) {
|
||||
proccessMenuNavigation(input, 2);
|
||||
if (entrySelected(input)) {
|
||||
if (this->selectedOption == 0) {
|
||||
this->state = STATE_INSTALL_MENU;
|
||||
} else {
|
||||
this->state = STATE_REMOVE_STARTED;
|
||||
OSEnableHomeButtonMenu(false);
|
||||
}
|
||||
this->selectedOption = 0;
|
||||
return;
|
||||
}
|
||||
} else if (this->state == STATE_REMOVE_STARTED) {
|
||||
this->state = STATE_REMOVE_COLDBOOT;
|
||||
} else if (this->state == STATE_REMOVE_COLDBOOT) {
|
||||
auto result = InstallerService::patchSystemXML("storage_slc_installer:/config", *this->systemMenuTitleId);
|
||||
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");
|
||||
}
|
||||
if (IOSUHAX_FSA_FlushVolume(fsaFd, "/vol/system") == 0) {
|
||||
DEBUG_FUNCTION_LINE("Flushed slc");
|
||||
}
|
||||
IOSUHAX_FSA_Close(fsaFd);
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE("Failed to open fsa");
|
||||
}
|
||||
this->state = STATE_REMOVE_AROMA;
|
||||
}
|
||||
} else if (this->state == STATE_REMOVE_AROMA) {
|
||||
auto result = InstallerService::restoreAppFiles(this->appInfo->path);
|
||||
if (result != InstallerService::SUCCESS) {
|
||||
setError(ERROR_INSTALLER_ERROR);
|
||||
this->installerError = result;
|
||||
} else {
|
||||
this->state = STATE_REMOVE_SUCCESS;
|
||||
}
|
||||
} else if (this->state == STATE_REMOVE_SUCCESS) {
|
||||
if (entrySelected(input)) {
|
||||
OSShutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -345,8 +431,24 @@ void ApplicationState::checkPatchPossible() {
|
||||
if (result != InstallerService::SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE("ERROR: %s", InstallerService::ErrorMessage(result).c_str());
|
||||
}
|
||||
this->state = STATE_CHECK_PATCH_POSSIBLE_DONE;
|
||||
|
||||
if (this->rpxAlreadyPatched) {
|
||||
this->state = STATE_CHECK_REMOVAL_POSSIBLE;
|
||||
} else {
|
||||
this->state = STATE_INSTALL_MENU;
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationState::checkRemovalPossible() {
|
||||
this->removalPossible = false;
|
||||
|
||||
this->systemMenuTitleId = InstallerService::getSystemMenuTitleId();
|
||||
if (this->systemMenuTitleId) {
|
||||
this->removalPossible = InstallerService::checkSystemXML("storage_slc_installer:/config", *this->systemMenuTitleId) == InstallerService::SUCCESS;
|
||||
this->removalPossible &= InstallerService::isBackupAvailable(this->appInfo->path);
|
||||
}
|
||||
|
||||
this->state = STATE_INSTALL_MENU;
|
||||
}
|
||||
|
||||
void ApplicationState::getAppInformation() {
|
||||
|
@ -21,7 +21,8 @@ public:
|
||||
STATE_WELCOME_SCREEN,
|
||||
STATE_GET_APP_INFORMATION,
|
||||
STATE_CHECK_PATCH_POSSIBLE,
|
||||
STATE_CHECK_PATCH_POSSIBLE_DONE,
|
||||
STATE_CHECK_REMOVAL_POSSIBLE,
|
||||
STATE_INSTALL_MENU,
|
||||
STATE_INSTALL_CHOOSE_COLDBOOT,
|
||||
STATE_INSTALL_NO_COLDBOOT_ALLOWED,
|
||||
STATE_INSTALL_CONFIRM_DIALOG,
|
||||
@ -31,7 +32,12 @@ public:
|
||||
STATE_INSTALL_COS,
|
||||
STATE_INSTALL_RPX,
|
||||
STATE_INSTALL_SYSTEM_XML,
|
||||
STATE_INSTALL_SUCCESS
|
||||
STATE_INSTALL_SUCCESS,
|
||||
STATE_REMOVE_CONFIRM_DIALOG,
|
||||
STATE_REMOVE_STARTED,
|
||||
STATE_REMOVE_COLDBOOT,
|
||||
STATE_REMOVE_AROMA,
|
||||
STATE_REMOVE_SUCCESS
|
||||
};
|
||||
|
||||
ApplicationState();
|
||||
@ -44,6 +50,8 @@ public:
|
||||
|
||||
void checkPatchPossible();
|
||||
|
||||
void checkRemovalPossible();
|
||||
|
||||
void getAppInformation();
|
||||
|
||||
std::optional<appInformation> appInfo;
|
||||
@ -69,11 +77,13 @@ private:
|
||||
bool fstPatchPossible = false;
|
||||
bool cosPatchPossible = false;
|
||||
bool systemXMLPatchPossible = false;
|
||||
bool removalPossible = false;
|
||||
|
||||
eGameState state;
|
||||
eErrorState error = ERROR_NONE;
|
||||
uint64_t coldbootTitleId;
|
||||
_gList_t *coldbootTitle;
|
||||
std::optional<uint64_t> systemMenuTitleId;
|
||||
bool fstAlreadyPatched;
|
||||
bool rpxAlreadyPatched;
|
||||
bool cosAlreadyPatched;
|
||||
|
@ -186,6 +186,35 @@ std::optional<appInformation> InstallerService::getInstalledAppInformation() {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<uint64_t> InstallerService::getSystemMenuTitleId() {
|
||||
auto mcpHandle = (int32_t) MCP_Open();
|
||||
auto titleCount = (uint32_t) 1;
|
||||
auto *titleList = (MCPTitleListType *) memalign(32, sizeof(MCPTitleListType) * titleCount);
|
||||
|
||||
MCP_TitleListByAppType(mcpHandle, MCP_APP_TYPE_SYSTEM_MENU, &titleCount, titleList, sizeof(MCPTitleListType) * titleCount);
|
||||
|
||||
MCP_Close(mcpHandle);
|
||||
|
||||
if (titleCount != 1) {
|
||||
DEBUG_FUNCTION_LINE("More than 1 System Menu title!? Found %d", titleCount);
|
||||
return {};
|
||||
}
|
||||
|
||||
if ((titleList->titleId != 0x0005001010040000L) &&
|
||||
(titleList->titleId != 0x0005001010040100L) &&
|
||||
(titleList->titleId != 0x0005001010040200L))
|
||||
{
|
||||
DEBUG_FUNCTION_LINE("Unrecognized System Menu title");
|
||||
return {};
|
||||
}
|
||||
|
||||
uint64_t menuTid = titleList->titleId;
|
||||
|
||||
free(titleList);
|
||||
|
||||
return menuTid;
|
||||
}
|
||||
|
||||
InstallerService::eResults InstallerService::patchFSTData(uint8_t *fstData, uint32_t size) {
|
||||
auto *fstHeader = (FSTHeader *) fstData;
|
||||
if (strncmp(FSTHEADER_MAGIC, fstHeader->magic, 3) != 0) {
|
||||
@ -317,6 +346,77 @@ std::string InstallerService::ErrorMessage(InstallerService::eResults error) {
|
||||
|
||||
}
|
||||
|
||||
bool InstallerService::isBackupAvailable(const std::string &path) {
|
||||
std::string backupList[] = {
|
||||
{"/content/title.fst.bak"},
|
||||
{"/content/cos.xml.bak" },
|
||||
{"/content/safe.rpx.bak" },
|
||||
};
|
||||
|
||||
for (auto &backupEntry : backupList) {
|
||||
std::string backupFile = path + backupEntry;
|
||||
std::string backupSha1 = backupFile + ".sha1";
|
||||
|
||||
if (!FSUtils::CheckFile(backupFile.c_str())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!FSUtils::CheckFile(backupSha1.c_str())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t *sha1FileCont;
|
||||
uint32_t sha1FileSize;
|
||||
FSUtils::LoadFileToMem(backupSha1.c_str(), &sha1FileCont, &sha1FileSize);
|
||||
if (!sha1FileCont) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string savedHash = std::string(sha1FileCont, sha1FileCont + sha1FileSize);
|
||||
std::string fileHash = Utils::hashFile(backupFile);
|
||||
if (fileHash != savedHash) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
InstallerService::eResults InstallerService::restoreAppFiles(const std::string &path) {
|
||||
std::string backupList[][2] = {
|
||||
{"/code/title.fst", "/content/title.fst.bak"},
|
||||
{"/code/cos.xml", "/content/cos.xml.bak" },
|
||||
{"/code/safe.rpx", "/content/safe.rpx.bak" },
|
||||
};
|
||||
|
||||
for (auto &backupOp : backupList) {
|
||||
std::string destPath = path + backupOp[0];
|
||||
std::string backupPath = path + backupOp[1];
|
||||
|
||||
if (!FSUtils::copyFile(backupPath, destPath)) {
|
||||
DEBUG_FUNCTION_LINE("Failed to copy files");
|
||||
return FAILED_TO_COPY_FILES;
|
||||
}
|
||||
|
||||
std::string srcHash = Utils::hashFile(backupPath);
|
||||
std::string dstHash = Utils::hashFile(destPath);
|
||||
if (srcHash != dstHash) {
|
||||
DEBUG_FUNCTION_LINE("Hashes do not match. %s %s", srcHash.c_str(), dstHash.c_str());
|
||||
return FAILED_TO_CHECK_HASH_COPIED_FILES;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &backupOp : backupList) {
|
||||
std::string backupPath = path + backupOp[1];
|
||||
std::string backupSha1Path = backupPath + ".sha1";
|
||||
::remove(backupPath.c_str());
|
||||
::remove(backupSha1Path.c_str());
|
||||
}
|
||||
|
||||
DEBUG_FUNCTION_LINE("Successfully restored app files");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
InstallerService::eResults InstallerService::backupAppFiles(const std::string &path) {
|
||||
std::string backupList[][2] = {
|
||||
{"/code/title.fst", "/content/title.fst.bak"},
|
||||
|
@ -43,6 +43,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isBackupAvailable(const std::string &path);
|
||||
|
||||
static eResults restoreAppFiles(const std::string &path);
|
||||
|
||||
static eResults backupAppFiles(const std::string &path);
|
||||
|
||||
static eResults patchCOS(const std::string &path, char *hash);
|
||||
@ -55,6 +59,8 @@ public:
|
||||
|
||||
static std::optional<appInformation> getInstalledAppInformation();
|
||||
|
||||
static std::optional<uint64_t> getSystemMenuTitleId();
|
||||
|
||||
static std::string ErrorMessage(eResults error);
|
||||
|
||||
static std::string ErrorDescription(eResults error);
|
||||
|
Loading…
Reference in New Issue
Block a user