Improved unit type detection code

This commit is contained in:
d0k3 2017-02-26 13:35:37 +01:00
parent cbcdea231a
commit 81e7b1fbb6
12 changed files with 40 additions and 55 deletions

View File

@ -1,15 +0,0 @@
#include "common.h"
#include "platform.h"
#define CONFIG_PLATFORM_REG ((volatile u32*)0x10140FFC)
Platform GetUnitPlatform()
{
switch (*CONFIG_PLATFORM_REG) {
case 7:
return PLATFORM_N3DS;
case 1:
default:
return PLATFORM_3DS;
}
}

View File

@ -1,8 +0,0 @@
#pragma once
typedef enum {
PLATFORM_3DS,
PLATFORM_N3DS,
} Platform;
Platform GetUnitPlatform();

13
source/common/unittype.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include "common.h"
// see: https://3dbrew.org/wiki/CONFIG11_Registers
#define IS_O3DS ((*(vu32*) 0x10140FFC) != 0x7)
// see: https://www.3dbrew.org/wiki/Memory_layout#ARM9_ITCM
// see: https://www.3dbrew.org/wiki/OTP_Registers#Plaintext_OTP
#define IS_DEVKIT ((*(vu8*) (0x01FFB800+0x19)) != 0x0)
// see: https://3dbrew.org/wiki/CONFIG11_Registers
#define IS_A9LH ((*(vu32*) 0x101401C0) == 0)

View File

@ -1,5 +1,5 @@
#include "ramdrive.h" #include "ramdrive.h"
#include "platform.h" #include "unittype.h"
static u8* ramdrv_buffer = NULL; static u8* ramdrv_buffer = NULL;
static u32 ramdrv_size = 0; static u32 ramdrv_size = 0;
@ -26,7 +26,7 @@ u64 GetRamDriveSize(void) {
} }
void InitRamDrive(void) { void InitRamDrive(void) {
if (GetUnitPlatform() == PLATFORM_3DS) { if (IS_O3DS) {
ramdrv_buffer = RAMDRV_BUFFER_O3DS; ramdrv_buffer = RAMDRV_BUFFER_O3DS;
ramdrv_size = RAMDRV_SIZE_O3DS; ramdrv_size = RAMDRV_SIZE_O3DS;
} else { } else {

View File

@ -2,7 +2,7 @@
#include "fsdrive.h" #include "fsdrive.h"
#include "virtual.h" #include "virtual.h"
#include "image.h" #include "image.h"
#include "nand.h" #include "unittype.h"
#include "ui.h" #include "ui.h"
#define PATH_SYS_LVL1 "S:/twln.bin", "S:/twlp.bin" #define PATH_SYS_LVL1 "S:/twln.bin", "S:/twlp.bin"
@ -41,7 +41,7 @@ bool CheckWritePermissions(const char* path) {
for (u32 i = 0; (i < sizeof(path_lvl1) / sizeof(char*)) && (lvl < 1); i++) for (u32 i = 0; (i < sizeof(path_lvl1) / sizeof(char*)) && (lvl < 1); i++)
if (strncmp(path, path_lvl1[i], 256) == 0) lvl = 1; if (strncmp(path, path_lvl1[i], 256) == 0) lvl = 1;
} }
if (!CheckA9lh()) { // changed SysNAND permission levels on non-A9LH if (!IS_A9LH) { // changed SysNAND permission levels on non-A9LH
if ((drvtype & DRV_CTRNAND) || (lvl == 2)) lvl = 3; if ((drvtype & DRV_CTRNAND) || (lvl == 2)) lvl = 3;
} }
perm = perms[lvl]; perm = perms[lvl];
@ -172,7 +172,7 @@ bool SetWritePermissions(u32 perm, bool add_perm) {
return false; return false;
break; break;
case PERM_SYS_LVL3: case PERM_SYS_LVL3:
if (!ShowUnlockSequence(5, "!THIS IS YOUR ONLY WARNING!\n \nYou want to enable SysNAND\nlvl3 writing permissions.\n \nThis enables you to OVERWRITE\n%s", CheckA9lh() ? "your A9LH installation and/or\nBRICK your console!" : "essential system files and/or\nBRICK your console!")) if (!ShowUnlockSequence(5, "!THIS IS YOUR ONLY WARNING!\n \nYou want to enable SysNAND\nlvl3 writing permissions.\n \nThis enables you to OVERWRITE\n%s", IS_A9LH ? "your A9LH installation and/or\nBRICK your console!" : "essential system files and/or\nBRICK your console!"))
return false; return false;
break; break;
case PERM_ALL: // maybe get rid of this (???) case PERM_ALL: // maybe get rid of this (???)

View File

@ -3,7 +3,7 @@
#include "ui.h" #include "ui.h"
#include "fsperm.h" #include "fsperm.h"
#include "filetype.h" #include "filetype.h"
#include "platform.h" #include "unittype.h"
#include "aes.h" #include "aes.h"
#include "sha.h" #include "sha.h"
#include "vff.h" #include "vff.h"
@ -1427,7 +1427,7 @@ u32 InjectHealthAndSafety(const char* path, const char* destdrv) {
continue; continue;
region = secinfo[0x100]; region = secinfo[0x100];
if (region >= sizeof(tidlow_hs_o3ds) / sizeof(u32)) continue; if (region >= sizeof(tidlow_hs_o3ds) / sizeof(u32)) continue;
tidlow_hs = (GetUnitPlatform() == PLATFORM_3DS) ? tidlow_hs = (IS_O3DS) ?
tidlow_hs_o3ds[region] : tidlow_hs_n3ds[region]; tidlow_hs_o3ds[region] : tidlow_hs_n3ds[region];
break; break;
} }

View File

@ -8,7 +8,7 @@
#include "gameutil.h" #include "gameutil.h"
#include "nandutil.h" #include "nandutil.h"
#include "filetype.h" #include "filetype.h"
#include "platform.h" #include "unittype.h"
#include "nand.h" #include "nand.h"
#include "virtual.h" #include "virtual.h"
#include "vcart.h" #include "vcart.h"
@ -239,7 +239,7 @@ u32 SdFormatMenu(void) {
return 1; return 1;
} }
if (CheckA9lh()) { if (IS_A9LH) {
InitSDCardFS(); // on A9LH: copy the payload from mem to SD root InitSDCardFS(); // on A9LH: copy the payload from mem to SD root
FileSetData("0:/arm9loaderhax.bin", (u8*) 0x23F00000, 0x40000, 0, true); FileSetData("0:/arm9loaderhax.bin", (u8*) 0x23F00000, 0x40000, 0, true);
DeinitSDCardFS(); DeinitSDCardFS();
@ -616,7 +616,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
bool buildable = (FTYPE_BUILDABLE(filetype)); bool buildable = (FTYPE_BUILDABLE(filetype));
bool buildable_legit = (FTYPE_BUILDABLE_L(filetype)); bool buildable_legit = (FTYPE_BUILDABLE_L(filetype));
bool hsinjectable = (FTYPE_HSINJECTABLE(filetype)); bool hsinjectable = (FTYPE_HSINJECTABLE(filetype));
bool restorable = (FTYPE_RESTORABLE(filetype) && CheckA9lh() && !(drvtype & DRV_SYSNAND)); bool restorable = (FTYPE_RESTORABLE(filetype) && IS_A9LH && !(drvtype & DRV_SYSNAND));
bool ebackupable = (FTYPE_EBACKUP(filetype)); bool ebackupable = (FTYPE_EBACKUP(filetype));
bool xorpadable = (FTYPE_XORPAD(filetype)); bool xorpadable = (FTYPE_XORPAD(filetype));
bool launchable = ((FTYPE_PAYLOAD(filetype)) && (drvtype & DRV_FAT)); bool launchable = ((FTYPE_PAYLOAD(filetype)) && (drvtype & DRV_FAT));
@ -1069,7 +1069,7 @@ u32 GodMode() {
InitExtFS(); InitExtFS();
// could also check for a9lh via this: ((*(vu32*) 0x101401C0) == 0) // could also check for a9lh via this: ((*(vu32*) 0x101401C0) == 0)
if ((GetUnitPlatform() == PLATFORM_N3DS) && !CheckSlot0x05Crypto()) { if ((!IS_O3DS) && !CheckSlot0x05Crypto()) {
if (!ShowPrompt(true, "Warning: slot0x05 crypto fail!\nCould not set up slot0x05keyY.\nContinue?")) { if (!ShowPrompt(true, "Warning: slot0x05 crypto fail!\nCould not set up slot0x05keyY.\nContinue?")) {
DeinitExtFS(); DeinitExtFS();
DeinitSDCardFS(); DeinitSDCardFS();

View File

@ -1,14 +1,14 @@
#include "nand.h" #include "nand.h"
#include "fsdrive.h" #include "fsdrive.h"
#include "fsutil.h" #include "fsutil.h"
#include "platform.h" #include "unittype.h"
#include "keydb.h" #include "keydb.h"
#include "aes.h" #include "aes.h"
#include "sha.h" #include "sha.h"
#include "sdmmc.h" #include "sdmmc.h"
#include "image.h" #include "image.h"
#define NAND_MIN_SECTORS ((GetUnitPlatform() == PLATFORM_N3DS) ? NAND_MIN_SECTORS_N3DS : NAND_MIN_SECTORS_O3DS) #define NAND_MIN_SECTORS ((!IS_O3DS) ? NAND_MIN_SECTORS_N3DS : NAND_MIN_SECTORS_O3DS)
static u8 slot0x05KeyY[0x10] = { 0x00 }; // need to load this from FIRM0 / external file static u8 slot0x05KeyY[0x10] = { 0x00 }; // need to load this from FIRM0 / external file
static const u8 slot0x05KeyY_sha256[0x20] = { // hash for slot0x05KeyY (16 byte) static const u8 slot0x05KeyY_sha256[0x20] = { // hash for slot0x05KeyY (16 byte)
@ -67,7 +67,7 @@ u32 LoadKeyYFromP9(u8* key, const u8* keyhash, u32 offset, u32 keyslot)
u8 header[0x200]; u8 header[0x200];
// check arm9loaderhax // check arm9loaderhax
if (!CheckA9lh() || (offset < (offsetA9l + 0x0800))) return 1; if (!IS_A9LH || (offset < (offsetA9l + 0x0800))) return 1;
// section 2 (arm9loader) header of FIRM // section 2 (arm9loader) header of FIRM
// this is @0x066A00 in FIRM90 & FIRM81 // this is @0x066A00 in FIRM90 & FIRM81
@ -98,7 +98,7 @@ bool InitNandCrypto(void)
{ {
// part #0: KeyX / KeyY for secret sector 0x96 // part #0: KeyX / KeyY for secret sector 0x96
// on a9lh this MUST be run before accessing the SHA register in any other way // on a9lh this MUST be run before accessing the SHA register in any other way
if (CheckA9lh()) { // for a9lh if (IS_A9LH) { // for a9lh
// store the current SHA256 from register // store the current SHA256 from register
memcpy(OtpSha256, (void*) REG_SHAHASH, 32); memcpy(OtpSha256, (void*) REG_SHAHASH, 32);
} else { } else {
@ -128,7 +128,7 @@ bool InitNandCrypto(void)
// part #2: TWL KEY // part #2: TWL KEY
// see: https://www.3dbrew.org/wiki/Memory_layout#ARM9_ITCM // see: https://www.3dbrew.org/wiki/Memory_layout#ARM9_ITCM
if (CheckA9lh()) { // only for a9lh if (IS_A9LH) { // only for a9lh
u32* TwlCustId = (u32*) (0x01FFB808); u32* TwlCustId = (u32*) (0x01FFB808);
u8 TwlKeyX[16] __attribute__((aligned(32))); u8 TwlKeyX[16] __attribute__((aligned(32)));
u8 TwlKeyY[16] __attribute__((aligned(32))); u8 TwlKeyY[16] __attribute__((aligned(32)));
@ -196,11 +196,6 @@ bool CheckSector0x96Crypto(void)
return (sha_cmp(slot0x11Key95_sha256, buffer, 16, SHA256_MODE) == 0); return (sha_cmp(slot0x11Key95_sha256, buffer, 16, SHA256_MODE) == 0);
} }
bool CheckA9lh(void)
{
return ((*(vu32*) 0x101401C0) == 0);
}
void CryptNand(u8* buffer, u32 sector, u32 count, u32 keyslot) void CryptNand(u8* buffer, u32 sector, u32 count, u32 keyslot)
{ {
u32 mode = (sector >= SECTOR_TWL + SIZE_TWL) ? AES_CNT_CTRNAND_MODE : AES_CNT_TWLNAND_MODE; u32 mode = (sector >= SECTOR_TWL + SIZE_TWL) ? AES_CNT_CTRNAND_MODE : AES_CNT_TWLNAND_MODE;
@ -368,7 +363,7 @@ u32 CheckNandHeader(u8* header)
// header type check // header type check
if (memcmp(header + 0x100, nand_magic_n3ds, sizeof(nand_magic_n3ds) == 0) == 0) if (memcmp(header + 0x100, nand_magic_n3ds, sizeof(nand_magic_n3ds) == 0) == 0)
return (GetUnitPlatform() == PLATFORM_3DS) ? 0 : NAND_TYPE_N3DS; return (IS_O3DS) ? 0 : NAND_TYPE_N3DS;
else if (memcmp(header + 0x100, nand_magic_o3ds, sizeof(nand_magic_o3ds) == 0) == 0) else if (memcmp(header + 0x100, nand_magic_o3ds, sizeof(nand_magic_o3ds) == 0) == 0)
return NAND_TYPE_O3DS; return NAND_TYPE_O3DS;
@ -379,13 +374,13 @@ u32 CheckNandType(u32 nand_src)
{ {
if (ReadNandSectors(NAND_BUFFER, 0, 1, 0xFF, nand_src) != 0) if (ReadNandSectors(NAND_BUFFER, 0, 1, 0xFF, nand_src) != 0)
return 0; return 0;
if (memcmp(NAND_BUFFER + 0x100, nand_magic_n3ds, 0x60) == 0) { if (memcmp(NAND_BUFFER + 0x100, nand_magic_n3ds, sizeof(nand_magic_n3ds)) == 0) {
return (GetUnitPlatform() == PLATFORM_3DS) ? 0 : NAND_TYPE_N3DS; return (IS_O3DS) ? 0 : NAND_TYPE_N3DS;
} else if (memcmp(NAND_BUFFER + 0x100, nand_magic_o3ds, 0x60) == 0) { } else if (memcmp(NAND_BUFFER + 0x100, nand_magic_o3ds, sizeof(nand_magic_o3ds)) == 0) {
u8 magic[8] = {0xE9, 0x00, 0x00, 0x43, 0x54, 0x52, 0x20, 0x20}; u8 magic[8] = {0xE9, 0x00, 0x00, 0x43, 0x54, 0x52, 0x20, 0x20};
if (ReadNandSectors(NAND_BUFFER, 0x5CAE5, 1, 0x04, nand_src) != 0) if (ReadNandSectors(NAND_BUFFER, 0x5CAE5, 1, 0x04, nand_src) != 0)
return 0; return 0;
return ((GetUnitPlatform() == PLATFORM_3DS) || (memcmp(magic, NAND_BUFFER, 8) == 0)) ? return ((IS_O3DS) || (memcmp(magic, NAND_BUFFER, 8) == 0)) ?
NAND_TYPE_O3DS : NAND_TYPE_NO3DS; NAND_TYPE_O3DS : NAND_TYPE_NO3DS;
} }

View File

@ -37,7 +37,6 @@
bool InitNandCrypto(void); bool InitNandCrypto(void);
bool CheckSlot0x05Crypto(void); bool CheckSlot0x05Crypto(void);
bool CheckSector0x96Crypto(void); bool CheckSector0x96Crypto(void);
bool CheckA9lh(void);
void CryptNand(u8* buffer, u32 sector, u32 count, u32 keyslot); void CryptNand(u8* buffer, u32 sector, u32 count, u32 keyslot);
void CryptSector0x96(u8* buffer, bool encrypt); void CryptSector0x96(u8* buffer, bool encrypt);

View File

@ -6,6 +6,7 @@
#include "image.h" #include "image.h"
#include "fsinit.h" #include "fsinit.h"
#include "fsperm.h" #include "fsperm.h"
#include "unittype.h"
#include "sha.h" #include "sha.h"
#include "ui.h" #include "ui.h"
#include "vff.h" #include "vff.h"
@ -194,7 +195,7 @@ u32 SafeRestoreNandDump(const char* path) {
if ((ValidateNandDump(path) != 0) && // NAND dump validation if ((ValidateNandDump(path) != 0) && // NAND dump validation
!ShowPrompt(true, "NAND dump corrupt or not from console.\nStill continue?")) !ShowPrompt(true, "NAND dump corrupt or not from console.\nStill continue?"))
return 1; return 1;
if (!CheckA9lh()) { if (!IS_A9LH) {
ShowPrompt(false, "Error: A9LH not detected."); ShowPrompt(false, "Error: A9LH not detected.");
return 1; return 1;
} }

View File

@ -1,5 +1,5 @@
#include "vmem.h" #include "vmem.h"
#include "platform.h" #include "unittype.h"
#define VFLAG_N3DS_ONLY (1UL<<31) #define VFLAG_N3DS_ONLY (1UL<<31)
@ -29,7 +29,7 @@ bool ReadVMemDir(VirtualFile* vfile, VirtualDir* vdir) { // uses a generic vdir
memcpy(vfile, templates + vdir->index, sizeof(VirtualFile)); memcpy(vfile, templates + vdir->index, sizeof(VirtualFile));
// process special flag // process special flag
if ((vfile->flags & VFLAG_N3DS_ONLY) && (GetUnitPlatform() != PLATFORM_N3DS)) if ((vfile->flags & VFLAG_N3DS_ONLY) && (IS_O3DS))
continue; // this is not on O3DS consoles continue; // this is not on O3DS consoles
// found if arriving here // found if arriving here

View File

@ -2,7 +2,7 @@
#include "nand.h" #include "nand.h"
#include "agbsave.h" #include "agbsave.h"
#include "essentials.h" #include "essentials.h"
#include "platform.h" #include "unittype.h"
#define VFLAG_ON_O3DS NAND_TYPE_O3DS #define VFLAG_ON_O3DS NAND_TYPE_O3DS
#define VFLAG_ON_N3DS NAND_TYPE_N3DS #define VFLAG_ON_N3DS NAND_TYPE_N3DS
@ -52,7 +52,7 @@ bool ReadVNandDir(VirtualFile* vfile, VirtualDir* vdir) { // uses a generic vdir
while (++vdir->index < n_templates) { while (++vdir->index < n_templates) {
// get NAND type (O3DS/N3DS/NO3DS), workaround for empty EmuNAND // get NAND type (O3DS/N3DS/NO3DS), workaround for empty EmuNAND
u32 nand_type = CheckNandType(nand_src); u32 nand_type = CheckNandType(nand_src);
if (!nand_type) nand_type = (GetUnitPlatform() == PLATFORM_3DS) ? NAND_TYPE_O3DS : NAND_TYPE_N3DS; if (!nand_type) nand_type = (IS_O3DS) ? NAND_TYPE_O3DS : NAND_TYPE_N3DS;
// copy current template to vfile // copy current template to vfile
memcpy(vfile, templates + vdir->index, sizeof(VirtualFile)); memcpy(vfile, templates + vdir->index, sizeof(VirtualFile));