Mount twl_photo and deep HWInfo recovery

This commit is contained in:
Lillian Skinner 2024-11-26 05:05:12 -05:00
parent e476985f68
commit da2ae15e7c
No known key found for this signature in database
15 changed files with 308 additions and 74 deletions

View File

@ -46,6 +46,43 @@ I'm basing a lot of this off of my private DSi [NAND archive](https://nands.rand
- `0x790000`: retail and pandas
- `0x784000`: ISTC (needs confirmation) and ISTD
- `0x794000`: Happened when I deleted HWInfo and let SystemUpdater create it
- I mention prod and dev a lot. Prod (retail) DSis are the typical ones you would buy in stores. Dev DSis are used by developers for testing, or in factory hardware (I'm [excluding IS-TWLs](#do-you-support-is-twl-debuggercaptures) from this description). Prod and dev function the same, but the bootloader, apps/tickets/TMDs, certificates, photos, and HWInfo use different signing and encryption keys. Please keep these differences in mind when making changes to TwlNandTool.
## Do you support IS-TWL-DEBUGGER/CAPTUREs?
IS-TWLs are rarer, harder to fix, and have different firmware, so they have been blacklisted from TwlNandTool. However, I'd be happy to personally help you if your IS-TWL has an issue. Please contact me and *describe your problem in detail*.
## Creating AGING tests
AGING mode is used to create an automated set of tests. This can be used to find and fix certain issues without the need for user input. If you want to make an AGING test, just enable agingMode and load all the tests you need like this:
```c
agingMode = true; // disable user input on tests
success = true;
clearScreen(cSUB);
iprintf("\n>> Demo AGING test start ");
iprintf("\n--------------------------------");
// run all your functions as needed:
if (success && !importNandFirm(false)) {
success = false;
}
if (success && !readNandFirm()) {
success = false;
}
agingMode = false; // enable user input on tests
clearScreen(cSUB);
iprintf("\n>> Demo AGING test result ");
iprintf("\n--------------------------------");
if (success == true) {
iprintf("\nAll tests passed okay.");
setBackdropColorSub(0x1FE0); // green background
} else {
iprintf("\nTests failed!");
setBackdropColorSub(0x00FF); // red background
}
exitFunction(); // wait for user to confirm the result, then leave the AGING test
```
You can see a larger example AGING with `debug3()` in [main.c](arm9/src/main.c)
## Including system files
*B-b-but you have system files like the bootloader!* These files are required to boot a DSi and almost always cannot be custom made due to signing. This is a tool meant to fix every possible software brick, and to do so in an accessible way. Most people are not going to know how to recover a bootloader, find the right FontTable for their region, or get the correct and safe wlanfirm/sysmenuVersion. Even given a well written guide, I know the "what's a hex editor" or "what's a byte" messages all too well. It is not safe to force people to chase after things they may not understand. Especially when one wrong file will cause a brick, and the owner will be none the wiser.

View File

@ -10,6 +10,7 @@
#include "nand/nandfirm.h"
#include "nand/chipinfo.h"
#include "nand/sysfile.h"
#include "nand/hwinfo.h"
#include "video.h"
#include "nitrofs.h"
#include "font.h"
@ -45,7 +46,9 @@
*/
extern bool nand_Startup();
extern bool sdio_Startup();
bool legitHWInfo = false;
bool nandMounted = false;
bool nandPhotoMounted = false;
bool sdMounted = false;
bool agingMode = false;
bool success = false;
@ -190,7 +193,8 @@ int main(int argc, char **argv)
}
agingMode = true;
mountMain();
mountNAND(false);
mountNAND(true);
mountNitroFS();
agingMode = false;
mkdir("sd:/TwlNandTool", 0777);
@ -201,7 +205,7 @@ int main(int argc, char **argv)
if (keysDown() & KEY_START || keysDown() & KEY_SELECT) {
} else {
debug1();
recoverHWInfoDeep();
}
clearScreen(cSUB);
@ -325,10 +329,10 @@ int debug3(void) {
if (success == true && !nandPrintInfo()) {
success = false;
}
if (success == true && !nandFirmImport(true)) {
if (success == true && !importNandFirm(true)) {
success = false;
}
if (success == true && !nandFirmRead()) {
if (success == true && !readNandFirm()) {
success = false;
}
if (success == true && !repairMbr(true)) {
@ -337,19 +341,25 @@ int debug3(void) {
if (success == true && !readMbr()) {
success = false;
}
if (success == true && !mountMain()) {
if (!formatMain() && !formatPhoto() && !mountMain()) {
iprintf("\nNAND mount failed!");
if (success == true && !mountNAND(false)) {
if (!formatMain() && !mountNAND(false)) {
success = false;
} else {
nandMounted = true;
}
} else if (nandMounted == true) {
iprintf("\nNAND already mounted.");
} else {
nandMounted = true;
}
if (success == true && !filetestMain()) {
if (success == true && !mountNAND(true)) {
if (!formatPhoto() && !mountNAND(true)) {
success = false;
}
}
if (success == true && !recoverHWInfo(false)) {
if (success == true && !recoverHWInfoDeep()) {
success = false;
}
}
if (success == true && !filetestNAND(false)) {
success = false;
}
if (success == true && !filetestNAND(true)) {
success = false;
}
if (success == true && !makeSystemFolders()) {
@ -361,7 +371,10 @@ int debug3(void) {
if (success == true && !makeFontTable()) {
success = false;
}
if (success == true && !unmountMain()) {
if (success == true && !unmountNAND(false)) {
success = false;
}
if (success == true && !unmountNAND(true)) {
success = false;
}
if (success == true && !filetestNitro()) {

View File

@ -10,7 +10,9 @@
#include "video.h"
#include "nitrofs.h"
extern bool legitHWInfo;
extern bool nandMounted;
extern bool nandPhotoMounted;
extern bool sdMounted;
extern bool agingMode;
extern bool success;

View File

@ -164,29 +164,54 @@ void clearHelpMenu(Menu* m)
iprintf("\x1b[6;0H\x1b[K");
iprintf("\x1b[7;0H\x1b[K");
iprintf("\x1b[8;0H\x1b[K");
iprintf("\x1b[9;0H%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", (char)139, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)141);
iprintf("\x1b[9;0H\x1b[K");
iprintf("\x1b[10;0H\x1b[K");
iprintf("\x1b[11;0H\x1B[40m%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%cInfo%c%c%c%c%c", (char)138, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)134, (char)135, (char)136, (char)136, (char)136, (char)140);
iprintf("\x1B[30m\x1b[12;0H\x1b[K %s %s", m->header, VERSION);
iprintf("\x1b[13;0H\x1b[K Built on: %s", BUILD_DATE);
iprintf("\x1b[14;0H\x1b[K Made by: RMC/RVTR");
iprintf("\x1b[11;0H\x1b[K");
iprintf("\x1b[12;0H\x1b[K");
iprintf("\x1b[13;0H\x1b[K");
iprintf("\x1b[14;0H%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", (char)139, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)141);
iprintf("\x1b[15;0H\x1b[K");
iprintf("\x1b[16;0H\x1b[K");
iprintf("\x1b[17;0H\x1b[K Run on: %s\x1B[40m", consoleType);
iprintf("\x1b[18;0H%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\x1B[30m", (char)139, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)141);
iprintf("\x1b[16;0H\x1B[40m%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%cInfo%c%c%c%c%c", (char)138, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)134, (char)135, (char)136, (char)136, (char)136, (char)140);
iprintf("\x1B[30m\x1b[17;0H\x1b[K %s %s", m->header, VERSION);
iprintf("\x1b[18;0H\x1b[K %s RMC/RVTR", BUILD_DATE);
iprintf("\x1b[19;0H\x1b[K");
iprintf("\x1b[20;0H\x1b[K Serial: AAAMP1234567");
iprintf("\x1b[21;0H\x1b[K Version: v0.1A (ALL)");
iprintf("\x1b[22;0H\x1b[K Run on: %s\x1B[40m", consoleType);
iprintf("\x1b[23;0H%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\x1B[30m", (char)139, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)141);
}
void printHelpMenu(Menu* m)
{
if (!m) return;
consoleSet(cMAIN);
iprintf("\x1B[30m\x1b[1;0H %s", m->items[m->cursor].help);
}
void printDebugIDs(Menu* m)
{
if (!m) return;
consoleSet(cSUB);
iprintf("\x1b[22;0H[");
int i;
for (i = 8; i > 0;) {
i--;
printf("%02X", consoleID[i]);
}
iprintf("]\x1b[23;0H[");
for (i = 15; i > 0;) {
i--;
printf("%02X", CID[i]);
}
iprintf("]");
}
void printMenu(Menu* m, int level)
{
clearHelpMenu(m);
printHelpMenu(m);
printDebugIDs(m);
consoleSet(cSUB);
if (!m) return;

View File

@ -35,6 +35,7 @@ void resetMenu(Menu* m);
void clearMenu(Menu* m);
void clearHelpMenu(Menu* m);
void printHelpMenu(Menu* m);
void printDebugIDs(Menu* m);
void printMenu(Menu* m, int level);
bool moveCursor(Menu* m);

View File

@ -64,9 +64,12 @@ enum {
FSMENU_NULL,
FSMENU_MOUNT_MAIN,
FSMENU_UNMOUNT_MAIN,
FSMENU_MOUNT_PHOTO,
FSMENU_UNMOUNT_PHOTO,
FSMENU_MOUNT_NITRO,
FSMENU_NULL2,
FSMENU_FILETEST_MAIN,
FSMENU_FILETEST_PHOTO,
FSMENU_FILETEST_NITRO
};
@ -84,9 +87,12 @@ static int _fsMenu(int cursor)
addMenuItem(m, "------------------", NULL, 0, "");
addMenuItem(m, "Mount TWL_MAIN", NULL, 0, "Mount the TWL_MAIN partition.");
addMenuItem(m, "Unmount TWL_MAIN", NULL, 0, "Unmount the TWL_MAIN partition");
addMenuItem(m, "Mount TWL_PHOTO", NULL, 0, "Mount the TWL_PHOTO partition.");
addMenuItem(m, "Unmount TWL_PHOTO", NULL, 0, "Unmount the TWL_PHOTO partition");
addMenuItem(m, "Mount NitroFS", NULL, 0, "Mount the ROM filesystem.");
addMenuItem(m, "------------------", NULL, 0, "");
addMenuItem(m, "File test TWL_MAIN", NULL, 0, "Attempt to make/delete dummy\n file on NAND.");
addMenuItem(m, "File test TWL_PHOTO", NULL, 0, "Attempt to make/delete dummy\n file on NAND.");
addMenuItem(m, "File test NitroFS", NULL, 0, "Attempt to read file in\n NitroFS.");
m->cursor = cursor;
@ -148,11 +154,19 @@ int fsMain(void)
break;
case FSMENU_MOUNT_MAIN:
mountMain();
mountNAND(false);
break;
case FSMENU_UNMOUNT_MAIN:
unmountMain();
unmountNAND(false);
break;
case FSMENU_MOUNT_PHOTO:
mountNAND(true);
break;
case FSMENU_UNMOUNT_PHOTO:
unmountNAND(true);
break;
case FSMENU_MOUNT_NITRO:
@ -163,7 +177,11 @@ int fsMain(void)
break;
case FSMENU_FILETEST_MAIN:
filetestMain();
filetestNAND(false);
break;
case FSMENU_FILETEST_PHOTO:
filetestNAND(true);
break;
case FSMENU_FILETEST_NITRO:
@ -321,55 +339,82 @@ bool formatPhoto(void) {
return success;
}
bool mountMain(void) {
bool mountNAND(bool isPhoto) {
success = true;
clearScreen(cSUB);
iprintf("\n>> Mount TWL_MAIN ");
char partition_name[10];
snprintf(partition_name, 10, isPhoto ? "TWL_PHOTO" : "TWL_MAIN");
iprintf("\n>> Mount %s\n", partition_name);
iprintf("\n--------------------------------");
if (nandMounted == true) {
if (isPhoto ? nandPhotoMounted : nandMounted) {
if (!agingMode) {
agingMode = true;
unmountMain();
unmountNAND(isPhoto);
agingMode = false;
} else {
unmountMain();
unmountNAND(isPhoto);
}
}
clearScreen(cSUB);
iprintf("\n>> Mount TWL_MAIN ");
iprintf("\n>> Mount %s\n", partition_name);
iprintf("\n--------------------------------");
if (!nandio_startup()) {
iprintf("\nFailed startup!");
success = false;
}
if (success == true && !fatMountSimple("nand", &io_dsi_nand, true)) {
iprintf("\n\x1B[31mMount TWL_MAIN failed!\n\x1B[30m\nNAND must be repaired. Try...\n - Fixing MBR\n - Formatting TWL_MAIN");
success = false;
} else if (success == true) {
iprintf("\nTWL_MAIN mounted okay.");
nandio_unlock_writing();
nandMounted = true;
if (isPhoto) {
mbr_t mbr;
io_dsi_nand.readSectors(0, 1, &mbr);
if (success == true && !fatMount("photo", &io_dsi_nand, mbr.partitions[1].offset, 16, 8, false)) {
iprintf("\n\x1B[31mMount TWL_PHOTO failed!\n\x1B[30m\nNAND must be repaired. Try...\n - Fixing MBR\n - Formatting TWL_PHOTO");
success = false;
} else if (success == true) {
iprintf("\nTWL_PHOTO mounted okay.");
nandio_unlock_writing();
nandPhotoMounted = true;
}
} else {
if (success == true && !fatMountSimple("nand", &io_dsi_nand, true)) {
iprintf("\n\x1B[31mMount TWL_MAIN failed!\n\x1B[30m\nNAND must be repaired. Try...\n - Fixing MBR\n - Formatting TWL_MAIN");
success = false;
} else if (success == true) {
iprintf("\nTWL_MAIN mounted okay.");
nandio_unlock_writing();
nandMounted = true;
}
}
exitFunction();
return success;
}
bool unmountMain(void) {
bool unmountNAND(bool isPhoto) {
success = true;
clearScreen(cSUB);
iprintf("\n>> Unmount TWL_MAIN ");
char partition_name[10];
snprintf(partition_name, 10, isPhoto ? "TWL_PHOTO" : "TWL_MAIN");
char partition_path[10];
snprintf(partition_path, 10, isPhoto ? "photo" : "nand");
iprintf("\n>> Unmount %s\n", partition_name);
iprintf("\n--------------------------------");
if (nandMounted == true) {
iprintf("\nUnmounting NAND...");
fatUnmount("nand");
nandMounted = false;
if (isPhoto ? nandPhotoMounted : nandMounted) {
iprintf("\nUnmounting %s...", partition_name);
fatUnmount(partition_path);
if (isPhoto) {
nandPhotoMounted = false;
} else {
nandMounted = false;
}
// Unmounting NAND also unmounts the SD. Why???? Average dkp experience I guess.
sdMounted = false;
// I just don't want to interrupt the startup aging test
@ -382,17 +427,17 @@ bool unmountMain(void) {
}
clearScreen(cSUB);
iprintf("\n>> Umount TWL_MAIN ");
iprintf("\n>> Umount %s\n", partition_name);
iprintf("\n--------------------------------");
if (success) {
iprintf("\nTWL_MAIN unmounted okay.");
iprintf("\n%s unmounted okay.", partition_name);
} else {
iprintf("\nFailed to mount TWL_MAIN!");
iprintf("\nFailed to mount %s!", partition_name);
}
} else {
iprintf("\nNAND not mounted!\nDoing nothing.");
iprintf("\n%s not mounted!\nDoing nothing.", partition_name);
}
exitFunction();
@ -431,21 +476,32 @@ bool mountNitroFS(void) {
return success;
}
bool filetestMain(void) {
bool filetestNAND(bool isPhoto) {
success = true;
clearScreen(cSUB);
iprintf("\n>> Read TWL_MAIN file ");
char partition_name[10];
snprintf(partition_name, 10, isPhoto ? "TWL_PHOTO" : "TWL_MAIN");
char partition_path[10];
snprintf(partition_path, 10, isPhoto ? "photo" : "nand");
iprintf("\n>> Read %s file", partition_name);
iprintf("\n--------------------------------");
if (nandMounted == true) {
if (isPhoto ? nandPhotoMounted : nandMounted) {
printf("\nMaking temp folder...");
mkdir("nand:/tmp", 0777);
if (isPhoto) {
mkdir("photo:/tmp", 0777);
} else {
mkdir("nand:/tmp", 0777);
}
printf("\nOpening test file...\n");
char file_path[100];
snprintf(file_path, 100, "nand:/tmp/test.bin");
snprintf(file_path, 100, "%s:/tmp/test.bin", partition_path);
FILE *file = fopen(file_path, "wb");
printf("\n%s\n", file_path);
if(file) {
@ -480,10 +536,10 @@ bool filetestMain(void) {
iprintf("\nFile failed to open!");
}
remove(file_path);
//remove(file_path);
} else {
success = false;
iprintf("\nTWL_MAIN is not mounted!");
iprintf("\n%s is not mounted!", partition_name);
}
exitFunction();

View File

@ -20,9 +20,9 @@ bool readMbr(void);
bool repairMbr(bool autofix);
bool formatMain(void);
bool formatPhoto(void);
bool mountMain(void);
bool unmountMain(void);
bool mountNAND(bool isPhoto);
bool unmountNAND(bool isPhoto);
bool mountNitroFS(void);
bool filetestMain(void);
bool filetestNAND(bool isPhoto);
bool filetestNitro(void);

View File

@ -16,6 +16,7 @@
#include "../storage.h"
static size_t i;
bool hwinfofound = false;
hwsFormat hwsData = {0};
@ -40,7 +41,6 @@ bool loadHWInfoStruct() {
bool recoverHWInfo(bool simple) {
success = true;
bool hwinfofound = false;
clearScreen(cSUB);
iprintf("\n>> Recover HWInfo Secure ");
@ -154,7 +154,6 @@ bool recoverHWInfoOffset(int address) {
memset(sector_buf, 0, 512);
good_nandio_read(address + 0x91, 32, file_buf, true);
// 0x414E48
printf("\n ");
for (i = 0; i < 32; i++) {
printf("%02X", file_buf[i]);
@ -169,7 +168,7 @@ bool recoverHWInfoOffset(int address) {
success = true;
printf("\n\nLauncher TID found!");
good_nandio_read(address + 0x400 + 0x91, 32, file_buf2, true);
for (int i = 19; i < 32; i++) {
for (i = 19; i < 32; i++) {
if (file_buf[i] != file_buf2[i]) {
success = false;
break;
@ -199,6 +198,67 @@ bool recoverHWInfoOffset(int address) {
return success;
}
// 0x10EE00 is the twl_main start
// 0xCDF1200 is the twl_main size
bool recoverHWInfoDeep(void) {
success = false;
clearScreen(cSUB);
iprintf("\n>> Recover HWInfo Secure Deep ");
iprintf("\n--------------------------------");
int j = 0;
iprintf("\nSearching raw TWL_MAIN...\n\n ");
for (i = 0; i < (0xCDF1200 / SECTOR_SIZE); i++) {
good_nandio_read(0x10EE00 + (i * SECTOR_SIZE), SECTOR_SIZE, file_buf, true);
if (j >= 20) {
char currentPicto = downloadPlayLoading(69);
printf("\b%c", currentPicto);
j = 0;
} else {
j++;
}
if (file_buf[0 + 0xA1] == 0x41 && file_buf[1 + 0xA1] == 0x4E && file_buf[2 + 0xA1] == 0x48) {
iprintf("\b\x1B[1A\nFound xANH");
success = true;
good_nandio_read(0x10EE00 + (i * SECTOR_SIZE), SECTOR_SIZE, file_buf, true);
good_nandio_read(0x10EE00 + (i * SECTOR_SIZE) + 0x400, SECTOR_SIZE, file_buf2, true);
for (int j = 0xA4; j < 0xB4; j++) {
if (file_buf[j] != file_buf2[j]) {
success = false;
iprintf("\nExtra data didn't match.");
}
}
iprintf("\nDone.");
if (success == true) { // also if (verify)
memset(sector_buf, 0, SECTOR_SIZE);
good_nandio_read(0x10EE00 + (i * SECTOR_SIZE), SECTOR_SIZE, sector_buf, true);
printf("\n%02X%02X%02X", sector_buf[0 + 0xA1], sector_buf[1 + 0xA1], sector_buf[2 + 0xA1]);
if (!agingMode) {
agingMode = true;
success = saveHWInfoSDMC();
agingMode = false;
} else {
success = saveHWInfoSDMC();
}
clearScreen(cSUB);
iprintf("\n>> Recover HWInfo Secure Deep ");
iprintf("\n--------------------------------");
if (success == true) {
iprintf("\nRecovery was ok!");
} else {
iprintf("\nFailed to back up HWInfo!");
}
exitFunction();
return success;
}
}
}
exitFunction();
return success;
}
bool saveHWInfoSDMC(void) {
success = true;
clearScreen(cSUB);

View File

@ -75,5 +75,6 @@ extern hwsFormat hwsData;
bool clearHWInfoStruct();
bool loadHWInfoStruct();
bool recoverHWInfo(bool simple);
bool recoverHWInfoDeep();
bool recoverHWInfoOffset(int address);
bool saveHWInfoSDMC(void);

View File

@ -74,15 +74,15 @@ int nfMain(void)
{
case NFMENU_CHECK_VER:
nandFirmRead();
readNandFirm();
break;
case NFMENU_IMPORT:
nandFirmImport(false);
importNandFirm(false);
break;
case NFMENU_IMPORT_SDMC:
nandFirmImport(true);
importNandFirm(true);
break;
}
}
@ -93,7 +93,7 @@ int nfMain(void)
return 0;
}
bool nandFirmRead(void) {
bool readNandFirm(void) {
success = true;
clearScreen(cSUB);
@ -119,7 +119,7 @@ bool nandFirmRead(void) {
return success;
}
bool nandFirmImport(bool sdmc) {
bool importNandFirm(bool sdmc) {
success = true;
clearScreen(cSUB);

View File

@ -17,5 +17,5 @@ void wait(int ticks);
int nfMain(void);
bool nandFirmRead(void);
bool nandFirmImport(bool sdmc);
bool readNandFirm(void);
bool importNandFirm(bool sdmc);

View File

@ -18,14 +18,14 @@
/************************ Constants / Defines *********************************/
static const mbr_partition_t ptable_DSi[MBR_PARTITIONS] = {
const mbr_partition_t ptable_DSi[MBR_PARTITIONS] = {
{0u, {3u, 24u, 4u}, 6u, {15u, 224u, 59u}, 0x00000877u, 0x00066f89u},
{0u, {2u, 206u, 60u}, 6u, {15u, 224u, 190u}, 0x0006784u, 0x000105b3u},
{0u, {2u, 222u, 191u}, 1u, {15u, 224u, 191u}, 0x00077e5u, 0x000001a3u},
{0u, {2u, 206u, 60u}, 6u, {15u, 224u, 190u}, 0x0006784du, 0x000105b3u},
{0u, {2u, 222u, 191u}, 1u, {15u, 224u, 191u}, 0x00077e5du, 0x000001a3u},
{0u, {0u, 0u, 0u}, 0u, {0u, 0u, 0u}, 0u, 0u}
};
static const mbr_partition_t ptable_3DS[MBR_PARTITIONS] = {
const mbr_partition_t ptable_3DS[MBR_PARTITIONS] = {
{0u, {4u, 24u, 0u}, 6u, {1u, 160u, 63u}, 0x0000009u, 0x00047da9u},
{0u, {4u, 142u, 64u}, 6u, {1u, 160u, 195u}, 0x0004808u, 0x000105b3u},
{0u, {0u, 0u, 0u}, 0u, {0u, 0u, 0u}, 0u, 0u},
@ -99,9 +99,47 @@ int parse_mbr(const uint8_t sector0[SECTOR_SIZE], const int is3DS)
ref_ptable = is3DS?ptable_3DS:ptable_DSi;
// only test the 1st partition now, we've seen variations on the 3rd partition
// and after all we only care about the 1st partition
if (memcmp(ref_ptable, m->partitions, sizeof(mbr_partition_t)))
if (memcmp(&ref_ptable[0], &m->partitions[0], sizeof(mbr_partition_t)))
{
return -2;
}
if (memcmp(&ref_ptable[1], &m->partitions[1], sizeof(mbr_partition_t)))
{
return -2;
}
return 0;
}
/*
// return 0 for valid MBR
int parse_mbr(const uint8_t sector0[SECTOR_SIZE], int is3DS, int verbose) {
const mbr_t *m = (mbr_t*)sector0;
const mbr_partition_t *ref_ptable; // reference partition table
int ret = 0;
if (m->boot_signature_0 != 0x55 || m->boot_signature_1 != 0xaa) {
//printf("invalid boot signature(0x55, 0xaa)\n");
ret = -1;
}
if (!is3DS) {
for (unsigned i = 0; i < sizeof(m->bootstrap); ++i) {
if (m->bootstrap[i]) {
//printf("bootstrap on DSi should be all zero\n");
ret = 0;
break;
}
}
ref_ptable = ptable_DSi;
} else {
ref_ptable = ptable_3DS;
}
// Only check the first two as those are the only ones we mount
// There's some variation in the 3rd
for(int i = 0; i < 2; i++) {
if (memcmp(&ref_ptable[i], &m->partitions[i], sizeof(mbr_partition_t))) {
//printf("invalid partition table\n");
ret = -2;
}
}
return ret;
}
*/

View File

@ -90,6 +90,7 @@ int sysfileMain(void)
break;
case SYSFILEMENU_RECOVER2:
recoverHWInfoDeep();
break;
case SYSFILEMENU_NULL:

Binary file not shown.

Binary file not shown.