mirror of
https://github.com/rvtr/unlaunch-installer_dev.git
synced 2026-01-26 13:43:08 -05:00
Handle nocash footer embedding into nand
Another step the unlaunch installer does but wasn't being handled yet
This commit is contained in:
parent
bfdd89218d
commit
351d4547b3
@ -8,6 +8,7 @@
|
|||||||
#include "unlaunch.h"
|
#include "unlaunch.h"
|
||||||
#include "nitrofs.h"
|
#include "nitrofs.h"
|
||||||
#include "deviceList.h"
|
#include "deviceList.h"
|
||||||
|
#include "nocashFooter.h"
|
||||||
|
|
||||||
volatile bool programEnd = false;
|
volatile bool programEnd = false;
|
||||||
static volatile bool arm7Exiting = false;
|
static volatile bool arm7Exiting = false;
|
||||||
@ -22,7 +23,9 @@ static const char* splashSoundBinaryPatchPath = NULL;
|
|||||||
static const char* customBgPath = NULL;
|
static const char* customBgPath = NULL;
|
||||||
volatile bool charging = false;
|
volatile bool charging = false;
|
||||||
volatile u8 batteryLevel = 0;
|
volatile u8 batteryLevel = 0;
|
||||||
static bool wantsUnsafeUnlaunchUninstall = false;
|
static bool advancedOptionsUnlocked = false;
|
||||||
|
static bool needsNocashFooterToBeWritten = false;
|
||||||
|
static NocashFooter computedNocashFooter;
|
||||||
|
|
||||||
PrintConsole topScreen;
|
PrintConsole topScreen;
|
||||||
PrintConsole bottomScreen;
|
PrintConsole bottomScreen;
|
||||||
@ -35,6 +38,7 @@ enum {
|
|||||||
MAIN_MENU_SAFE_UNLAUNCH_INSTALL,
|
MAIN_MENU_SAFE_UNLAUNCH_INSTALL,
|
||||||
MAIN_MENU_EXIT,
|
MAIN_MENU_EXIT,
|
||||||
MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP,
|
MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP,
|
||||||
|
MAIN_MENU_WRITE_NOCASH_FOOTER_ONLY,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void setupScreens()
|
static void setupScreens()
|
||||||
@ -94,8 +98,11 @@ static int mainMenu(int cursor)
|
|||||||
addMenuItem(m, soundPatchesStr, NULL, foundUnlaunchInstallerVersion == v2_0 && !disableAllPatches && splashSoundBinaryPatchPath != NULL, false);
|
addMenuItem(m, soundPatchesStr, NULL, foundUnlaunchInstallerVersion == v2_0 && !disableAllPatches && splashSoundBinaryPatchPath != NULL, false);
|
||||||
addMenuItem(m, installUnlaunchStr, NULL, foundUnlaunchInstallerVersion != INVALID && !unlaunchFound, false);
|
addMenuItem(m, installUnlaunchStr, NULL, foundUnlaunchInstallerVersion != INVALID && !unlaunchFound, false);
|
||||||
addMenuItem(m, "Exit", NULL, true, false);
|
addMenuItem(m, "Exit", NULL, true, false);
|
||||||
if(wantsUnsafeUnlaunchUninstall)
|
if(advancedOptionsUnlocked)
|
||||||
|
{
|
||||||
addMenuItem(m, "Uninstall unlaunch no backup", NULL, unlaunchFound, false);
|
addMenuItem(m, "Uninstall unlaunch no backup", NULL, unlaunchFound, false);
|
||||||
|
addMenuItem(m, "Write nocash footer", NULL, needsNocashFooterToBeWritten, false);
|
||||||
|
}
|
||||||
|
|
||||||
m->cursor = cursor;
|
m->cursor = cursor;
|
||||||
|
|
||||||
@ -116,7 +123,7 @@ static int mainMenu(int cursor)
|
|||||||
if (keysDown() & KEY_A)
|
if (keysDown() & KEY_A)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(wantsUnsafeUnlaunchUninstall)
|
if(advancedOptionsUnlocked)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int held = keysHeld();
|
int held = keysHeld();
|
||||||
@ -135,8 +142,9 @@ static int mainMenu(int cursor)
|
|||||||
}
|
}
|
||||||
if (konamiCode == 5)
|
if (konamiCode == 5)
|
||||||
{
|
{
|
||||||
wantsUnsafeUnlaunchUninstall = true;
|
advancedOptionsUnlocked = true;
|
||||||
addMenuItem(m, "Uninstall unlaunch no backup", NULL, unlaunchFound, false);
|
addMenuItem(m, "Uninstall unlaunch no backup", NULL, unlaunchFound, false);
|
||||||
|
addMenuItem(m, "Write nocash footer", NULL, needsNocashFooterToBeWritten, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,6 +197,25 @@ int main(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NocashFooter footer;
|
||||||
|
|
||||||
|
nandio_read_nocash_footer(&footer);
|
||||||
|
nandio_construct_nocash_footer(&computedNocashFooter);
|
||||||
|
|
||||||
|
if(!(needsNocashFooterToBeWritten = !isFooterValid(&footer)))
|
||||||
|
{
|
||||||
|
if(memcmp(&footer, &computedNocashFooter, sizeof(footer)) != 0)
|
||||||
|
{
|
||||||
|
messageBox("\x1B[31mError:\x1B[33m This console has a\n"
|
||||||
|
"nocash footer embedded in its\n"
|
||||||
|
"nand that doesn't match the one\n"
|
||||||
|
"generated.\n"
|
||||||
|
"The footer already present will\n"
|
||||||
|
"be overwritten.");
|
||||||
|
needsNocashFooterToBeWritten = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (batteryLevel < 7 && !charging)
|
while (batteryLevel < 7 && !charging)
|
||||||
{
|
{
|
||||||
if (choiceBox("\x1B[47mBattery is too low!\nPlease plug in the console.\n\nContinue?") == NO)
|
if (choiceBox("\x1B[47mBattery is too low!\nPlease plug in the console.\n\nContinue?") == NO)
|
||||||
@ -292,7 +319,18 @@ int main(int argc, char **argv)
|
|||||||
case MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL:
|
case MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL:
|
||||||
case MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP:
|
case MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP:
|
||||||
if(unlaunchFound && nandio_unlock_writing()) {
|
if(unlaunchFound && nandio_unlock_writing()) {
|
||||||
bool unsafeUninstall = wantsUnsafeUnlaunchUninstall && cursor == MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP;
|
bool unsafeUninstall = advancedOptionsUnlocked && cursor == MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP;
|
||||||
|
printf("Uninstalling");
|
||||||
|
if(needsNocashFooterToBeWritten)
|
||||||
|
{
|
||||||
|
printf("Writing nocash footer\n");
|
||||||
|
if(!nandio_write_nocash_footer(&computedNocashFooter))
|
||||||
|
{
|
||||||
|
messageBox("Failed to write nocash footer");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
needsNocashFooterToBeWritten = false;
|
||||||
|
}
|
||||||
if(uninstallUnlaunch(retailConsole, hnaaUnlaunchFound, retailLauncherTmdPath, unsafeUninstall))
|
if(uninstallUnlaunch(retailConsole, hnaaUnlaunchFound, retailLauncherTmdPath, unsafeUninstall))
|
||||||
{
|
{
|
||||||
messageBox("Uninstall successful!\n");
|
messageBox("Uninstall successful!\n");
|
||||||
@ -340,6 +378,16 @@ int main(int argc, char **argv)
|
|||||||
&& nandio_unlock_writing())
|
&& nandio_unlock_writing())
|
||||||
{
|
{
|
||||||
printf("Installing\n");
|
printf("Installing\n");
|
||||||
|
if(needsNocashFooterToBeWritten)
|
||||||
|
{
|
||||||
|
printf("Writing nocash footer\n");
|
||||||
|
if(!nandio_write_nocash_footer(&computedNocashFooter))
|
||||||
|
{
|
||||||
|
messageBox("Failed to write nocash footer");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
needsNocashFooterToBeWritten = false;
|
||||||
|
}
|
||||||
if(installUnlaunch(retailConsole,
|
if(installUnlaunch(retailConsole,
|
||||||
retailLauncherTmdPresentAndToBePatched ? retailLauncherTmdPath : NULL,
|
retailLauncherTmdPresentAndToBePatched ? retailLauncherTmdPath : NULL,
|
||||||
disableAllPatches,
|
disableAllPatches,
|
||||||
@ -357,6 +405,18 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MAIN_MENU_WRITE_NOCASH_FOOTER_ONLY:
|
||||||
|
if(needsNocashFooterToBeWritten)
|
||||||
|
{
|
||||||
|
if(!nandio_write_nocash_footer(&computedNocashFooter))
|
||||||
|
{
|
||||||
|
messageBox("Failed to write nocash footer");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
needsNocashFooterToBeWritten = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case MAIN_MENU_EXIT:
|
case MAIN_MENU_EXIT:
|
||||||
programEnd = true;
|
programEnd = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -10,6 +10,8 @@
|
|||||||
#include "nandio.h"
|
#include "nandio.h"
|
||||||
#include "u128_math.h"
|
#include "u128_math.h"
|
||||||
|
|
||||||
|
#define NOCASH_FOOTER_SECTOR 2044
|
||||||
|
|
||||||
/************************ Function Protoypes **********************************/
|
/************************ Function Protoypes **********************************/
|
||||||
|
|
||||||
static bool nandio_startup();
|
static bool nandio_startup();
|
||||||
@ -51,7 +53,16 @@ void nandio_set_fat_sig_fix(u32 offset)
|
|||||||
fat_sig_fix_offset = offset;
|
fat_sig_fix_offset = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void getConsoleID(u8 *consoleID)
|
void getCID(u8 *CID)
|
||||||
|
{
|
||||||
|
vu8* CIDbuff = (vu8*)0x2FFD7BC;
|
||||||
|
for(int i = 0; i < 16; ++i)
|
||||||
|
{
|
||||||
|
CID[i] = CIDbuff[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void getConsoleID(u8 *consoleID)
|
||||||
{
|
{
|
||||||
vu8 *fifo=(vu8*)0x02300000; //shared mem address that has our computed key3 stuff
|
vu8 *fifo=(vu8*)0x02300000; //shared mem address that has our computed key3 stuff
|
||||||
u8 key[16]; //key3 normalkey - keyslot 3 is used for DSi/twln NAND crypto
|
u8 key[16]; //key3 normalkey - keyslot 3 is used for DSi/twln NAND crypto
|
||||||
@ -89,6 +100,7 @@ static bool nandio_startup()
|
|||||||
|
|
||||||
u8 consoleID[8];
|
u8 consoleID[8];
|
||||||
u8 consoleIDfixed[8];
|
u8 consoleIDfixed[8];
|
||||||
|
u8 CID[16];
|
||||||
|
|
||||||
// Get ConsoleID
|
// Get ConsoleID
|
||||||
getConsoleID(consoleID);
|
getConsoleID(consoleID);
|
||||||
@ -97,8 +109,10 @@ static bool nandio_startup()
|
|||||||
consoleIDfixed[i] = consoleID[7-i];
|
consoleIDfixed[i] = consoleID[7-i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCID(CID);
|
||||||
|
|
||||||
// iprintf("sector 0 is %s\n", is3DS ? "3DS" : "DSi");
|
// iprintf("sector 0 is %s\n", is3DS ? "3DS" : "DSi");
|
||||||
dsi_crypt_init((const u8*)consoleIDfixed, (const u8*)0x2FFD7BC, is3DS);
|
dsi_crypt_init((const u8*)consoleIDfixed, (const u8*)CID, is3DS);
|
||||||
dsi_nand_crypt(sector_buf, sector_buf, 0, SECTOR_SIZE / AES_BLOCK_SIZE);
|
dsi_nand_crypt(sector_buf, sector_buf, 0, SECTOR_SIZE / AES_BLOCK_SIZE);
|
||||||
|
|
||||||
parse_mbr(sector_buf, is3DS);
|
parse_mbr(sector_buf, is3DS);
|
||||||
@ -144,6 +158,49 @@ static bool read_sectors(sec_t start, sec_t len, void *buffer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nandio_construct_nocash_footer(NocashFooter* footer)
|
||||||
|
{
|
||||||
|
u8 CID[16];
|
||||||
|
u8 consoleID[8];
|
||||||
|
|
||||||
|
getCID(CID);
|
||||||
|
getConsoleID(consoleID);
|
||||||
|
|
||||||
|
constructNocashFooter(footer, CID, consoleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nandio_read_nocash_footer(NocashFooter* footer)
|
||||||
|
{
|
||||||
|
if(!nand_ReadSectors(NOCASH_FOOTER_SECTOR, 1, crypt_buf))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(footer, crypt_buf, sizeof(NocashFooter));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nandio_write_nocash_footer(NocashFooter* footer)
|
||||||
|
{
|
||||||
|
if (writingLocked)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(!nand_ReadSectors(NOCASH_FOOTER_SECTOR, 1, crypt_buf))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(crypt_buf, footer, sizeof(NocashFooter));
|
||||||
|
|
||||||
|
|
||||||
|
if(!nand_WriteSectors(NOCASH_FOOTER_SECTOR, 1, crypt_buf))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// len is guaranteed <= CRYPT_BUF_LEN
|
// len is guaranteed <= CRYPT_BUF_LEN
|
||||||
static bool write_sectors(sec_t start, sec_t len, const void *buffer)
|
static bool write_sectors(sec_t start, sec_t len, const void *buffer)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <nds/disc_io.h>
|
#include <nds/disc_io.h>
|
||||||
|
#include "../nocashFooter.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -26,6 +27,10 @@ extern bool nandio_unlock_writing();
|
|||||||
extern bool nandio_force_fat_fix();
|
extern bool nandio_force_fat_fix();
|
||||||
extern void nandio_synchronize_fats();
|
extern void nandio_synchronize_fats();
|
||||||
|
|
||||||
|
extern void nandio_construct_nocash_footer(NocashFooter* footer);
|
||||||
|
extern bool nandio_read_nocash_footer(NocashFooter* footer);
|
||||||
|
extern bool nandio_write_nocash_footer(NocashFooter* footer);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
17
arm9/src/nocashFooter.c
Normal file
17
arm9/src/nocashFooter.c
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "nocashFooter.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static const char* nocashMagicString = "DSi eMMC CID/CPU";
|
||||||
|
|
||||||
|
bool isFooterValid(const NocashFooter* footer)
|
||||||
|
{
|
||||||
|
return memcmp(nocashMagicString, footer->footerID, sizeof(footer->footerID)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void constructNocashFooter(NocashFooter* footer, const u8* CID, const u8* consoleID)
|
||||||
|
{
|
||||||
|
memset(footer, 0, sizeof(NocashFooter));
|
||||||
|
memcpy(footer->footerID, nocashMagicString, sizeof(footer->footerID));
|
||||||
|
memcpy(footer->CID, CID, sizeof(footer->CID));
|
||||||
|
memcpy(footer->consoleId, consoleID, sizeof(footer->consoleId));
|
||||||
|
}
|
||||||
23
arm9/src/nocashFooter.h
Normal file
23
arm9/src/nocashFooter.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef NOCASH_FOOTER_H
|
||||||
|
#define NOCASH_FOOTER_H
|
||||||
|
#include <nds/ndstypes.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct NocashFooter {
|
||||||
|
char footerID[16]; //DSi eMMC CID/CPU
|
||||||
|
u8 CID[16];
|
||||||
|
u8 consoleId[8];
|
||||||
|
u8 pad[0x18];
|
||||||
|
} NocashFooter;
|
||||||
|
|
||||||
|
bool isFooterValid(const NocashFooter* footer);
|
||||||
|
void constructNocashFooter(NocashFooter* footer, const u8* CID, const u8* consoleID);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
Reference in New Issue
Block a user