mirror of
https://github.com/rvtr/TwlNandTool.git
synced 2025-10-31 06:01:08 -04:00
HWInfo recovery by offsets
This commit is contained in:
parent
1ece9ae6a7
commit
e476985f68
@ -193,6 +193,7 @@ int main(int argc, char **argv)
|
|||||||
mountMain();
|
mountMain();
|
||||||
mountNitroFS();
|
mountNitroFS();
|
||||||
agingMode = false;
|
agingMode = false;
|
||||||
|
mkdir("sd:/TwlNandTool", 0777);
|
||||||
|
|
||||||
//
|
//
|
||||||
swiWaitForVBlank();
|
swiWaitForVBlank();
|
||||||
|
|||||||
@ -185,6 +185,7 @@ bool readMbr(void) {
|
|||||||
iprintf("\n>> MBR (Master Boot Record) ");
|
iprintf("\n>> MBR (Master Boot Record) ");
|
||||||
iprintf("\n--------------------------------");
|
iprintf("\n--------------------------------");
|
||||||
|
|
||||||
|
memset(sector_buf, 0, 512);
|
||||||
if(nand_ReadSectors(0, 1, sector_buf) == false) {
|
if(nand_ReadSectors(0, 1, sector_buf) == false) {
|
||||||
iprintf("\nCouldn't read NAND!\n");
|
iprintf("\nCouldn't read NAND!\n");
|
||||||
success = false;
|
success = false;
|
||||||
|
|||||||
226
arm9/src/nand/hwinfo.c
Normal file
226
arm9/src/nand/hwinfo.c
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
#include <nds.h>
|
||||||
|
#include <fat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
#include <nds/arm9/nand.h>
|
||||||
|
#include "f_xy.h"
|
||||||
|
#include "twltool/dsi.h"
|
||||||
|
#include "nandio.h"
|
||||||
|
#include "sector0.h"
|
||||||
|
#include "crypto.h"
|
||||||
|
#include "hwinfo.h"
|
||||||
|
#include "../message.h"
|
||||||
|
#include "../main.h"
|
||||||
|
#include "../video.h"
|
||||||
|
#include "../storage.h"
|
||||||
|
|
||||||
|
static size_t i;
|
||||||
|
|
||||||
|
hwsFormat hwsData = {0};
|
||||||
|
|
||||||
|
bool clearHWInfoStruct() {
|
||||||
|
// Dummy values are JPN. This seems to be the usual default.
|
||||||
|
for (int i = 0; i < 0x80; i++) {
|
||||||
|
hwsData.HWS_SIG[i] = 0xFF;
|
||||||
|
}
|
||||||
|
hwsData.HWS_HEADER = 0x01000000;
|
||||||
|
hwsData.HWS_SIZE = 0x1C000000;
|
||||||
|
hwsData.HWS_LANG = 0x01000000;
|
||||||
|
hwsData.HWS_PAD = 0x00000000;
|
||||||
|
hwsData.HWS_REGION = 0x00;
|
||||||
|
strcpy(hwsData.HWS_SERIAL, "AAAMP1234567"); // You're a real one if you understand this serial.
|
||||||
|
hwsData.HWS_TID = 0x50414E48;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool loadHWInfoStruct() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool recoverHWInfo(bool simple) {
|
||||||
|
success = true;
|
||||||
|
bool hwinfofound = false;
|
||||||
|
clearScreen(cSUB);
|
||||||
|
|
||||||
|
iprintf("\n>> Recover HWInfo Secure ");
|
||||||
|
iprintf("\n--------------------------------");
|
||||||
|
|
||||||
|
if (false){//nandMounted == true) {
|
||||||
|
|
||||||
|
printf("\nChecking mounted TWL_MAIN...");
|
||||||
|
if (false){//fileExists("nand:/sys/HWINFO_S.dat")) {
|
||||||
|
printf("\nFound HWInfo.");
|
||||||
|
if (copyFile("nand:/sys/HWINFO_S.dat", "sd:/HWINFO_S_BACKUP.dat") != 0) {
|
||||||
|
success = false;
|
||||||
|
printf("\nCouldn't copy HWInfo!");
|
||||||
|
} else {
|
||||||
|
printf("\nCopied okay.");
|
||||||
|
// Read the file to file_buf
|
||||||
|
// Some verification here
|
||||||
|
// Dump the thing to the struct
|
||||||
|
hwinfofound = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("\nCouldn't find HWInfo!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (simple == false) {
|
||||||
|
agingMode = true;
|
||||||
|
if (recoverHWInfoOffset(HWS_OFFSET_OTHER)) {
|
||||||
|
hwinfofound = true;
|
||||||
|
} else if (recoverHWInfoOffset(HWS_OFFSET_BOX)) {
|
||||||
|
hwinfofound = true;
|
||||||
|
} else if (recoverHWInfoOffset(HWS_OFFSET_HANDHELD)) {
|
||||||
|
hwinfofound = true;
|
||||||
|
}
|
||||||
|
agingMode = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearScreen(cSUB);
|
||||||
|
iprintf("\n>> Recover HWInfo Secure ");
|
||||||
|
iprintf("\n--------------------------------");
|
||||||
|
|
||||||
|
if (hwinfofound == true) {
|
||||||
|
iprintf("\nEverything was ok!");
|
||||||
|
} else {
|
||||||
|
iprintf("\nFailed to find HWInfo!");
|
||||||
|
}
|
||||||
|
exitFunction();
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Let's design recoverHWInfoOffset() around edge cases- meet the TWL-CPU-X4 (prototype).
|
||||||
|
The HWInfo is made up of one "real" HWInfo at the start, then a repeating secondary HWInfo to pad out to 16kb.
|
||||||
|
|
||||||
|
40E34ABB 0E81922C 0B2B24E5 CD4864D4 \
|
||||||
|
637F0199 D385B1AA A893F65E EDADE869 |
|
||||||
|
DA66D05D 5B31A897 E4AAF339 83FDD161 | "Real" HWInfo signature
|
||||||
|
128804B7 B7BA3C06 CD5304ED 9642181C |
|
||||||
|
A57B3B8B 695E1B37 6F7F220B 019C3932 |
|
||||||
|
8D45C9AE 99550547 71E77ECD 0C442E98 |
|
||||||
|
E2ECB154 BB4D7305 AF75D324 7231B36A |
|
||||||
|
A53677B1 EB4D0102 C8F31A43 EED93758 /
|
||||||
|
01000000 1C000000 01000000 00000000 <-- Region and language info
|
||||||
|
00414141 50503241 47303538 31000000 <-- Serial number
|
||||||
|
4A414E48 <-- Launcher TID
|
||||||
|
|
||||||
|
785E7A35 9A9B3C08 B9AAE1D5 02D5CD71 <-- No idea what this entire block is!
|
||||||
|
E7CFDC89 607EC36A 7A680E45 D0B30B50
|
||||||
|
BBD36599 99731FE3 91F61DDB 8788C2C1
|
||||||
|
50B19D58 ... and so on for 0x36C bytes.
|
||||||
|
|
||||||
|
64E1D65C 2649BBAA EDF4808A 3B5830A0 \
|
||||||
|
2E0C2E9A 481A0487 E9DC32DB A49BDA8C |
|
||||||
|
901B5647 2E3473CB 7317122A 2F7ECCE3 | "Real" HWInfo signature
|
||||||
|
C880187C 0EA2C230 DFFED67A D6AC7C54 |
|
||||||
|
98676C25 4B1726FF 3EAA6EE4 39A718CA |
|
||||||
|
EA2ECF98 9B41BA5F 3E32A49F 8262DE7E |
|
||||||
|
201585B4 E4D27B32 B4D501EE 2B098032 /
|
||||||
|
01000000 1C000000 01000000 00000000 <-- Region and language info
|
||||||
|
002E2E02 2E2E022E 2E022E59 02595902 <-- Serial number (completely broken in copies)
|
||||||
|
4A414E48 <-- Launcher TID
|
||||||
|
|
||||||
|
785E7A35 9A9B3C08 B9AAE1D5 02D5CD71 <-- This weird block appears again!
|
||||||
|
E7CFDC89 607EC36A 7A680E45 D0B30B50
|
||||||
|
BBD36599 99731FE3 91F61DDB 8788C2C1
|
||||||
|
50B19D58 ... and so on for 0x36C bytes.
|
||||||
|
|
||||||
|
I have no idea what testing this DSi went through. I can't say if this is unique to the X4 or not.
|
||||||
|
|
||||||
|
Anyways, the "weird block" is repeated between every HWInfo chunk. We can check for...
|
||||||
|
- The common part of the launcher TID (0x414E48)
|
||||||
|
- The first 13 bytes of the "weird block" data following the TID
|
||||||
|
|
||||||
|
Then to quickly verify this is a HWInfo, check if the "weird block" is repeated 0x36C + size of HWInfo later.
|
||||||
|
This will work on retail as well since the "weird block" here is 0xFF padding until 16kb, so it will always repeat.
|
||||||
|
|
||||||
|
Never let down the prototype enjoyers, even if this makes the process way more annoying!
|
||||||
|
|
||||||
|
Oh also here's another edge case!
|
||||||
|
The factory HWInfo Secure created by PRE_IMPORT will be entirely 0xFF.
|
||||||
|
It will only exist in units that did not leave the factory. This is less common, but there are hundreds of those DSis out there.
|
||||||
|
If you find 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF then do not proceed to recoverHWInfoDeep().
|
||||||
|
|
||||||
|
*/
|
||||||
|
bool recoverHWInfoOffset(int address) {
|
||||||
|
success = false;
|
||||||
|
clearScreen(cSUB);
|
||||||
|
iprintf("\n>> Recover HWInfo Secure Offset ");
|
||||||
|
iprintf("\n--------------------------------");
|
||||||
|
|
||||||
|
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]);
|
||||||
|
if ((i + 1) % 2 == 0) {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
if ((i - 31) % 8 == 0 && i != 32) {
|
||||||
|
printf("\n ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (file_buf[16] == 0x41 && file_buf[17] == 0x4E && file_buf[18] == 0x48) {
|
||||||
|
success = true;
|
||||||
|
printf("\n\nLauncher TID found!");
|
||||||
|
good_nandio_read(address + 0x400 + 0x91, 32, file_buf2, true);
|
||||||
|
for (int i = 19; i < 32; i++) {
|
||||||
|
if (file_buf[i] != file_buf2[i]) {
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (success == true) {
|
||||||
|
iprintf("\nSecondary data matches!\nClearing buffer...");
|
||||||
|
memset(sector_buf, 0, 0xA4);
|
||||||
|
iprintf("\nLoading HWInfo...");
|
||||||
|
good_nandio_read(address, 0xA4, file_buf, true);
|
||||||
|
memcpy(&hwsData, file_buf, 0xA4);
|
||||||
|
success = saveHWInfoSDMC();
|
||||||
|
|
||||||
|
clearScreen(cSUB);
|
||||||
|
iprintf("\n>> Recover HWInfo Secure Offset ");
|
||||||
|
iprintf("\n--------------------------------");
|
||||||
|
if (success == true) {
|
||||||
|
iprintf("\nRecovery was ok!");
|
||||||
|
} else {
|
||||||
|
iprintf("\nFailed to back up HWInfo!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// // Verify
|
||||||
|
// fopen fwrite fclose
|
||||||
|
}
|
||||||
|
exitFunction();
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool saveHWInfoSDMC(void) {
|
||||||
|
success = true;
|
||||||
|
clearScreen(cSUB);
|
||||||
|
|
||||||
|
iprintf("\n>> Save HWInfo Secure to SDMC ");
|
||||||
|
iprintf("\n--------------------------------");
|
||||||
|
|
||||||
|
// I need to do region checking (world/korea/china)
|
||||||
|
printf("\nRemoving old HWInfo...");
|
||||||
|
remove(HWS_PATH_SD);
|
||||||
|
printf("\nWriting HWInfo...");
|
||||||
|
|
||||||
|
FILE *file = fopen(HWS_PATH_SD, "wb");
|
||||||
|
if(file) {
|
||||||
|
fwrite(sector_buf, 1, 0xA4, file);
|
||||||
|
fclose(file);
|
||||||
|
iprintf("\nFile written.");
|
||||||
|
} else {
|
||||||
|
success = false;
|
||||||
|
iprintf("\nFile failed to open!");
|
||||||
|
}
|
||||||
|
|
||||||
|
exitFunction();
|
||||||
|
return success;
|
||||||
|
}
|
||||||
79
arm9/src/nand/hwinfo.h
Normal file
79
arm9/src/nand/hwinfo.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#include <nds.h>
|
||||||
|
#include <fat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
#include <nds/arm9/nand.h>
|
||||||
|
#include "f_xy.h"
|
||||||
|
#include "twltool/dsi.h"
|
||||||
|
#include "nandio.h"
|
||||||
|
#include "sector0.h"
|
||||||
|
#include "crypto.h"
|
||||||
|
#include "../message.h"
|
||||||
|
#include "../main.h"
|
||||||
|
#include "../video.h"
|
||||||
|
|
||||||
|
// Language code
|
||||||
|
// Differences in display text between Europe and North America are determined by combining region and language code
|
||||||
|
typedef enum TWL_LANG
|
||||||
|
{
|
||||||
|
LANG_JAPANESE = 0, // Japanese
|
||||||
|
LANG_ENGLISH = 1, // English
|
||||||
|
LANG_FRENCH = 2, // French
|
||||||
|
LANG_GERMAN = 3, // German
|
||||||
|
LANG_ITALIAN = 4, // Italian
|
||||||
|
LANG_SPANISH = 5, // Spanish
|
||||||
|
LANG_SIMP_CHINESE = 6, // Simplified Chinese
|
||||||
|
LANG_KOREAN = 7, // Korean
|
||||||
|
LANG_CODE_MAX
|
||||||
|
} TWL_LANG;
|
||||||
|
|
||||||
|
#define LANG_BITMAP_JAPAN ( ( 0x0001 << LANG_JAPANESE ) )
|
||||||
|
#define LANG_BITMAP_AMERICA ( ( 0x0001 << LANG_ENGLISH ) | \
|
||||||
|
( 0x0001 << LANG_FRENCH ) | \
|
||||||
|
( 0x0001 << LANG_SPANISH ) )
|
||||||
|
#define LANG_BITMAP_EUROPE ( ( 0x0001 << LANG_ENGLISH ) | \
|
||||||
|
( 0x0001 << LANG_FRENCH ) | \
|
||||||
|
( 0x0001 << LANG_GERMAN ) | \
|
||||||
|
( 0x0001 << LANG_ITALIAN ) | \
|
||||||
|
( 0x0001 << LANG_SPANISH ) )
|
||||||
|
#define LANG_BITMAP_AUSTRALIA ( ( 0x0001 << LANG_ENGLISH ) )
|
||||||
|
#define LANG_BITMAP_CHINA ( ( 0x0001 << LANG_SIMP_CHINESE ) )
|
||||||
|
#define LANG_BITMAP_KOREA ( ( 0x0001 << LANG_KOREAN ) )
|
||||||
|
|
||||||
|
#define HWINFO_FILE_LENGTH ( 16 * 1024 )
|
||||||
|
#define HWN_PATH "nand:/sys/HWINFO_N.dat"
|
||||||
|
#define HWS_PATH "nand:/sys/HWINFO_S.dat"
|
||||||
|
#define HWS_PATH_SD "sd:/TwlNandTool/HWINFO_S.dat"
|
||||||
|
|
||||||
|
#define HWS_OFFSET_BOX 0x784000
|
||||||
|
#define HWS_OFFSET_HANDHELD 0x790000
|
||||||
|
#define HWS_OFFSET_OTHER 0x794000
|
||||||
|
|
||||||
|
#define HWN_VERSION 1 // HW information format version (start no.:1)
|
||||||
|
#define HWS_VERSION 1 // HW information format version (start no.:1)
|
||||||
|
|
||||||
|
// I think these are for HWInfo Normal? This is from the TwlSDK Secure7 private package
|
||||||
|
//#define HWS_MOVABLE_UNIQUE_ID_LEN 16 // Unique ID Transferable between bodies
|
||||||
|
//#define HWS_MOVABLE_UNIQUE_ID_MASK 0x9865f16bd375414c // Unique ID shall be XOR of this value with serial no.
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 HWS_SIG[0x80];
|
||||||
|
u32 HWS_HEADER; // Always 0x01000000
|
||||||
|
u32 HWS_SIZE; // Always 0x1C000000
|
||||||
|
u32 HWS_LANG;
|
||||||
|
u32 HWS_PAD;
|
||||||
|
u8 HWS_REGION;
|
||||||
|
char HWS_SERIAL[15]; // Last 3 bytes are zerofilled.
|
||||||
|
// USA serials are 11, and others are 12.
|
||||||
|
// Kinda neat, seems like this padding was in case they needed more serials?
|
||||||
|
u32 HWS_TID;
|
||||||
|
} hwsFormat;
|
||||||
|
|
||||||
|
extern hwsFormat hwsData;
|
||||||
|
|
||||||
|
bool clearHWInfoStruct();
|
||||||
|
bool loadHWInfoStruct();
|
||||||
|
bool recoverHWInfo(bool simple);
|
||||||
|
bool recoverHWInfoOffset(int address);
|
||||||
|
bool saveHWInfoSDMC(void);
|
||||||
@ -52,10 +52,12 @@ static u32 fat_sig_fix_offset = 0;
|
|||||||
|
|
||||||
static u32 sector_buf32[SECTOR_SIZE/sizeof(u32)];
|
static u32 sector_buf32[SECTOR_SIZE/sizeof(u32)];
|
||||||
u8 *sector_buf = (u8*)sector_buf32;
|
u8 *sector_buf = (u8*)sector_buf32;
|
||||||
static u32 sector_buf232[SECTOR_SIZE/sizeof(u32)];
|
static u32 sector_buf322[SECTOR_SIZE/sizeof(u32)];
|
||||||
u8 *sector_buf2 = (u8*)sector_buf232;
|
u8 *sector_buf2 = (u8*)sector_buf322;
|
||||||
static u32 file_buf32[BUFFER_SIZE/sizeof(u32)];
|
static u32 file_buf32[BUFFER_SIZE/sizeof(u32)];
|
||||||
u8 *file_buf = (u8*)file_buf32;
|
u8 *file_buf = (u8*)file_buf32;
|
||||||
|
static u32 file_buf322[BUFFER_SIZE/sizeof(u32)];
|
||||||
|
u8 *file_buf2 = (u8*)file_buf322;
|
||||||
|
|
||||||
void nandio_set_fat_sig_fix(u32 offset)
|
void nandio_set_fat_sig_fix(u32 offset)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -46,6 +46,7 @@ typedef struct {
|
|||||||
|
|
||||||
extern u8 *sector_buf;
|
extern u8 *sector_buf;
|
||||||
extern u8 *file_buf;
|
extern u8 *file_buf;
|
||||||
|
extern u8 *file_buf2;
|
||||||
extern bool is3DS;
|
extern bool is3DS;
|
||||||
|
|
||||||
extern nandData nandInfo;
|
extern nandData nandInfo;
|
||||||
@ -57,6 +58,7 @@ extern u8 consoleIDfixed[8];
|
|||||||
|
|
||||||
extern bool good_nandio_write(int inputAddress, int inputLength, u8 *buffer, bool crypt);
|
extern bool good_nandio_write(int inputAddress, int inputLength, u8 *buffer, bool crypt);
|
||||||
extern bool good_nandio_write_file(int inputAddress, int inputLength, FILE *fp, bool crypt);
|
extern bool good_nandio_write_file(int inputAddress, int inputLength, FILE *fp, bool crypt);
|
||||||
|
extern bool good_nandio_read(int inputAddress, int inputLength, u8 *buffer, bool crypt);
|
||||||
|
|
||||||
extern bool nandio_startup();
|
extern bool nandio_startup();
|
||||||
extern bool nandio_shutdown();
|
extern bool nandio_shutdown();
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include "nandio.h"
|
#include "nandio.h"
|
||||||
#include "nandfirm.h"
|
#include "nandfirm.h"
|
||||||
#include "sysfile.h"
|
#include "sysfile.h"
|
||||||
|
#include "hwinfo.h"
|
||||||
#include "sector0.h"
|
#include "sector0.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "../message.h"
|
#include "../message.h"
|
||||||
@ -16,7 +17,7 @@
|
|||||||
#include "../video.h"
|
#include "../video.h"
|
||||||
#include "../storage.h"
|
#include "../storage.h"
|
||||||
|
|
||||||
static size_t i;
|
//static size_t i;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SYSFILEMENU_RECOVER,
|
SYSFILEMENU_RECOVER,
|
||||||
@ -29,71 +30,6 @@ enum {
|
|||||||
SYSFILEMENU_INIT_FONT
|
SYSFILEMENU_INIT_FONT
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
I just need to plan things out:
|
|
||||||
- verifyHWInfo
|
|
||||||
- Just test input HWInfo buffer
|
|
||||||
- recoverHWInfoShallow
|
|
||||||
- Check for easy to find file (in mounted TWL_MAIN, then by common HWInfo offsets)
|
|
||||||
- recoverHWInfoDeep
|
|
||||||
- Scrap the entire TWL_MAIN byte by byte to find HWInfo (last resort)
|
|
||||||
- resignHWInfo
|
|
||||||
|
|
||||||
Let's design this around edge cases- meet the TWL-CPU-X4 (prototype).
|
|
||||||
The HWInfo is made up of one "real" HWInfo at the start, then a repeating secondary HWInfo to pad out to 16kb.
|
|
||||||
|
|
||||||
40E34ABB 0E81922C 0B2B24E5 CD4864D4 \
|
|
||||||
637F0199 D385B1AA A893F65E EDADE869 |
|
|
||||||
DA66D05D 5B31A897 E4AAF339 83FDD161 | "Real" HWInfo signature
|
|
||||||
128804B7 B7BA3C06 CD5304ED 9642181C |
|
|
||||||
A57B3B8B 695E1B37 6F7F220B 019C3932 |
|
|
||||||
8D45C9AE 99550547 71E77ECD 0C442E98 |
|
|
||||||
E2ECB154 BB4D7305 AF75D324 7231B36A |
|
|
||||||
A53677B1 EB4D0102 C8F31A43 EED93758 /
|
|
||||||
01000000 1C000000 01000000 00000000 <-- Region and language info
|
|
||||||
00414141 50503241 47303538 31000000 <-- Serial number
|
|
||||||
4A414E48 <-- Launcher TID
|
|
||||||
|
|
||||||
785E7A35 9A9B3C08 B9AAE1D5 02D5CD71 <-- No idea what this entire block is!
|
|
||||||
E7CFDC89 607EC36A 7A680E45 D0B30B50
|
|
||||||
BBD36599 99731FE3 91F61DDB 8788C2C1
|
|
||||||
50B19D58 ... and so on for 0x36C bytes.
|
|
||||||
|
|
||||||
64E1D65C 2649BBAA EDF4808A 3B5830A0 \
|
|
||||||
2E0C2E9A 481A0487 E9DC32DB A49BDA8C |
|
|
||||||
901B5647 2E3473CB 7317122A 2F7ECCE3 | "Real" HWInfo signature
|
|
||||||
C880187C 0EA2C230 DFFED67A D6AC7C54 |
|
|
||||||
98676C25 4B1726FF 3EAA6EE4 39A718CA |
|
|
||||||
EA2ECF98 9B41BA5F 3E32A49F 8262DE7E |
|
|
||||||
201585B4 E4D27B32 B4D501EE 2B098032 /
|
|
||||||
01000000 1C000000 01000000 00000000 <-- Region and language info
|
|
||||||
002E2E02 2E2E022E 2E022E59 02595902 <-- Serial number (completely broken)
|
|
||||||
4A414E48 <-- Launcher TID
|
|
||||||
|
|
||||||
785E7A35 9A9B3C08 B9AAE1D5 02D5CD71 <-- This weird block appears again!
|
|
||||||
E7CFDC89 607EC36A 7A680E45 D0B30B50
|
|
||||||
BBD36599 99731FE3 91F61DDB 8788C2C1
|
|
||||||
50B19D58 ... and so on for 0x36C bytes.
|
|
||||||
|
|
||||||
I have no idea what testing this DSi went through. I can't say if this is unique to the X4 or not.
|
|
||||||
|
|
||||||
Anyways, the "weird block" is repeated between every HWInfo chunk. We can check for...
|
|
||||||
- 0x414E48: the common part of the launcher TID
|
|
||||||
- 0x785E7A35 9A9B3C08 B9AAE1D5 02D5CD71: the "weird block" data after the TID
|
|
||||||
|
|
||||||
Then to verify this is a HWInfo, check if the "weird block" is repeated 0x36C + size of HWInfo later.
|
|
||||||
This will work on retail as well since the "weird block" here is 0xFF padding until 16kb, so it will always repeat.
|
|
||||||
|
|
||||||
Never let down the prototype enjoyers, even if this makes the process way more annoying!
|
|
||||||
|
|
||||||
Oh also here's another edge case!
|
|
||||||
The factory HWInfo Secure created by PRE_IMPORT will be entirely 0xFF.
|
|
||||||
It will only exist in uninitialized units (did not leave the factory).
|
|
||||||
If you find 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF then do not proceed to recoverHWInfoDeep.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int _sysfileMenu(int cursor)
|
static int _sysfileMenu(int cursor)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -150,6 +86,7 @@ int sysfileMain(void)
|
|||||||
{
|
{
|
||||||
|
|
||||||
case SYSFILEMENU_RECOVER:
|
case SYSFILEMENU_RECOVER:
|
||||||
|
recoverHWInfo(false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYSFILEMENU_RECOVER2:
|
case SYSFILEMENU_RECOVER2:
|
||||||
@ -228,9 +165,9 @@ bool makeCertChain(void) {
|
|||||||
printf("\nRemoving old cert.sys...");
|
printf("\nRemoving old cert.sys...");
|
||||||
char nitro_path[100];
|
char nitro_path[100];
|
||||||
snprintf(nitro_path, 100, "nitro:/import/%s/cert.sys", consoleSignName);
|
snprintf(nitro_path, 100, "nitro:/import/%s/cert.sys", consoleSignName);
|
||||||
remove("nand:/sys/cert.sys");
|
remove(CERT_PATH);
|
||||||
printf("\nWriting cert.sys...");
|
printf("\nWriting cert.sys...");
|
||||||
if (copyFile(nitro_path, "nand:/sys/cert.sys") != 0) {
|
if (copyFile(nitro_path, CERT_PATH) != 0) {
|
||||||
success = false;
|
success = false;
|
||||||
} else {
|
} else {
|
||||||
printf("\nDone!");
|
printf("\nDone!");
|
||||||
@ -257,9 +194,9 @@ bool makeFontTable(void) {
|
|||||||
printf("\nRemoving old TWLFontTable...");
|
printf("\nRemoving old TWLFontTable...");
|
||||||
char nitro_path[100];
|
char nitro_path[100];
|
||||||
snprintf(nitro_path, 100, "nitro:/import/common/TWLFontTable.dat");
|
snprintf(nitro_path, 100, "nitro:/import/common/TWLFontTable.dat");
|
||||||
remove("nand:/sys/TWLFontTable.dat");
|
remove(FONT_PATH);
|
||||||
printf("\nWriting TWLFontTable (world)...");
|
printf("\nWriting TWLFontTable (world)...");
|
||||||
if (copyFile(nitro_path, "nand:/sys/TWLFontTable.dat") != 0) {
|
if (copyFile(nitro_path, FONT_PATH) != 0) {
|
||||||
success = false;
|
success = false;
|
||||||
} else {
|
} else {
|
||||||
printf("\nDone!");
|
printf("\nDone!");
|
||||||
@ -271,49 +208,4 @@ bool makeFontTable(void) {
|
|||||||
|
|
||||||
exitFunction();
|
exitFunction();
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
bool recoverHWInfo(void) {
|
|
||||||
success = true;
|
|
||||||
bool hwinfofound = false;
|
|
||||||
clearScreen(cSUB);
|
|
||||||
|
|
||||||
iprintf("\n>> Recover HWInfo Secure ");
|
|
||||||
iprintf("\n--------------------------------");
|
|
||||||
|
|
||||||
if (nandMounted == true) {
|
|
||||||
|
|
||||||
printf("\nChecking mounted TWL_MAIN...");
|
|
||||||
if (fileExists("nand:/sys/HWINFO_S.dat")) {
|
|
||||||
printf("\nFound HWInfo.");
|
|
||||||
if (copyFile("nand:/sys/HWINFO_S.dat", "sd:/HWINFO_S_BACKUP.dat") != 0) {
|
|
||||||
success = false;
|
|
||||||
printf("\nCouldn't copy HWInfo!");
|
|
||||||
} else {
|
|
||||||
printf("\nCopied okay.");
|
|
||||||
// Some verification here
|
|
||||||
hwinfofound = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
printf("\nCouldn't find HWInfo!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
iprintf("\nChecking common offsets...");
|
|
||||||
|
|
||||||
|
|
||||||
nandioread(offset + tidOffset, 16)
|
|
||||||
if (first 3 bytes == ANH)
|
|
||||||
nandioread(offset + tidOffset + 0x3CB, 16)
|
|
||||||
if (nandioread == nandioread)
|
|
||||||
// Verify
|
|
||||||
fopen fwrite fclose
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
exitFunction();
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@ -13,12 +13,19 @@
|
|||||||
#include "../main.h"
|
#include "../main.h"
|
||||||
#include "../video.h"
|
#include "../video.h"
|
||||||
|
|
||||||
|
#define CERT_PATH "nand:/sys/cert.sys"
|
||||||
|
#define DEVKP_PATH "nand:/sys/dev.kp"
|
||||||
|
#define HWID_PATH "nand:/sys/HWID.sgn"
|
||||||
|
#define FONT_PATH "nand:/sys/TWLFontTable.dat"
|
||||||
|
#define FLOG_PATH "nand:/sys/log/product.log"
|
||||||
|
#define CFG0_PATH "nand:/shared1/TWLCFG0.dat"
|
||||||
|
#define CFG1_PATH "nand:/shared1/TWLCFG1.dat"
|
||||||
|
#define WRAP_PATH "nand:/shared2/launcher/wrap.bin"
|
||||||
|
|
||||||
void wait(int ticks);
|
void wait(int ticks);
|
||||||
|
|
||||||
int sysfileMain();
|
int sysfileMain();
|
||||||
|
|
||||||
bool recoverHWInfo();
|
|
||||||
bool recoverHWInfoDeep();
|
|
||||||
bool makeSystemFolders();
|
bool makeSystemFolders();
|
||||||
bool makeCertChain();
|
bool makeCertChain();
|
||||||
bool makeFontTable();
|
bool makeFontTable();
|
||||||
Loading…
Reference in New Issue
Block a user