ctrtool: Updated exheader validation and ncch spec/flag recognition

This commit is contained in:
jakcron
2015-09-14 21:52:04 +08:00
parent 038aca268a
commit f8993e198a
5 changed files with 171 additions and 113 deletions
+3 -3
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32"> <ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration> <Configuration>Debug</Configuration>
@@ -18,13 +18,13 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v110</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v110</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+114 -97
View File
@@ -126,6 +126,58 @@ int exheader_programid_valid(exheader_context* ctx)
return 1; return 1;
} }
void exheader_deserialise_arm11localcaps_permissions(exheader_arm11systemlocalcaps_deserialised *caps, const exheader_arm11systemlocalcaps *arm11)
{
int i;
memset(caps, 0, sizeof(exheader_arm11systemlocalcaps_deserialised));
memcpy(caps->program_id, arm11->programid, 8);
caps->core_version = getle32(arm11->coreversion);
caps->enable_l2_cache = (arm11->flag[0] >> 0) & 1;
caps->use_additional_cores = (arm11->flag[0] >> 1) & 1;
caps->new3ds_systemmode = (arm11->flag[1] >> 0) & 15;
caps->ideal_processor = (arm11->flag[2] >> 0) & 3;
caps->affinity_mask = (arm11->flag[2] >> 2) & 3;
caps->old3ds_systemmode = (arm11->flag[2] >> 4) & 15;
caps->priority = (s8)arm11->flag[3];
// storage info
if (arm11->storageinfo.otherattributes & 2) {
caps->extdata_id = 0;
for (i = 0; i < 3; i++)
caps->other_user_saveid[i] = 0;
caps->use_other_variation_savedata = 0;
for (i = 0; i < 3; i++)
caps->accessible_saveid[i] = 0xfffff & (getle64(arm11->storageinfo.accessibleuniqueids) >> 20 * (2 - i));
for (i = 0; i < 3; i++)
caps->accessible_saveid[i+3] = 0xfffff & (getle64(arm11->storageinfo.extsavedataid) >> 20 * (2 - i));
}
else {
caps->extdata_id = getle64(arm11->storageinfo.extsavedataid);
for (i = 0; i < 3; i++)
caps->other_user_saveid[i] = 0xfffff & (getle64(arm11->storageinfo.accessibleuniqueids) >> 20 * (2 - i));
caps->use_other_variation_savedata = (getle64(arm11->storageinfo.accessibleuniqueids) >> 60) & 1;
for (i = 0; i < 6; i++)
caps->accessible_saveid[i] = 0;
}
caps->system_saveid[0] = getle32(arm11->storageinfo.systemsavedataid);
caps->system_saveid[1] = getle32(arm11->storageinfo.systemsavedataid + 4);
caps->accessinfo = getle64(arm11->storageinfo.accessinfo) & ~((u64)0xff00000000000000);
// Service Access Control
for (i = 0; i < 34; i++)
strncpy(caps->service_access_control[i], (char*)arm11->serviceaccesscontrol[i], 8);
caps->resource_limit_category = arm11->resourcelimitcategory;
}
int exheader_process(exheader_context* ctx, u32 actions) int exheader_process(exheader_context* ctx, u32 actions)
{ {
exheader_determine_key(ctx, actions); exheader_determine_key(ctx, actions);
@@ -135,13 +187,13 @@ int exheader_process(exheader_context* ctx, u32 actions)
if (ctx->header.codesetinfo.flags.flag & 1) if (ctx->header.codesetinfo.flags.flag & 1)
ctx->compressedflag = 1; ctx->compressedflag = 1;
exheader_deserialise_arm11localcaps_permissions(&ctx->system_local_caps, &ctx->header.arm11systemlocalcaps);
if (actions & VerifyFlag) if (actions & VerifyFlag)
exheader_verify(ctx); exheader_verify(ctx);
if (actions & InfoFlag) if (actions & InfoFlag)
{ exheader_print(ctx);
exheader_print(ctx);
}
return 1; return 1;
} }
@@ -397,11 +449,10 @@ void exheader_print_arm11accessinfo(exheader_context* ctx)
{ {
char str[100]; char str[100];
u64 i, bit; u64 i, bit;
u64 accessinfo = 0xffffffffffffff & getle64(ctx->header.arm11systemlocalcaps.storageinfo.accessinfo);
for(i = 0; i < 56; i++) for(i = 0; i < 56; i++)
{ {
bit = ((u64)1 << i); bit = ((u64)1 << i);
if((accessinfo & bit) == bit) if((ctx->system_local_caps.accessinfo & bit) == bit)
fprintf(stdout, " > %s\n",exheader_print_accessinfobit((u32)i,str)); fprintf(stdout, " > %s\n",exheader_print_accessinfobit((u32)i,str));
} }
} }
@@ -410,72 +461,21 @@ void exheader_print_arm11storageinfo(exheader_context* ctx)
{ {
u32 i; u32 i;
// Storage Info fprintf(stdout, "Ext savedata id: 0x%"PRIx64"\n",ctx->system_local_caps.extdata_id);
u32 systemsaveID[2];
u64 extdataID;
u32 otherusersaveID[3];
u32 accessiblesaveID[6];
u8 otherattibutes = ctx->header.arm11systemlocalcaps.storageinfo.otherattributes;
u8 accessOtherVariationSavedata = (getle64(ctx->header.arm11systemlocalcaps.storageinfo.accessibleuniqueids) & 0x1000000000000000) == 0x1000000000000000;
systemsaveID[0] = getle32(ctx->header.arm11systemlocalcaps.storageinfo.systemsavedataid);
systemsaveID[1] = getle32(ctx->header.arm11systemlocalcaps.storageinfo.systemsavedataid+4);
extdataID = getle64(ctx->header.arm11systemlocalcaps.storageinfo.extsavedataid);
for(i = 0; i < 3; i++)
{
accessiblesaveID[i] = 0xfffff & (getle64(ctx->header.arm11systemlocalcaps.storageinfo.accessibleuniqueids) >> 20*(2-i));
otherusersaveID[i] = 0xfffff & (getle64(ctx->header.arm11systemlocalcaps.storageinfo.accessibleuniqueids) >> 20*(2-i));
}
for(i = 0; i < 3; i++)
{
accessiblesaveID[i+3] = 0xfffff & (getle64(ctx->header.arm11systemlocalcaps.storageinfo.extsavedataid) >> 20*(2-i));
}
if(otherattibutes & 2)
{
extdataID = 0;
for(i = 0; i < 3; i++)
otherusersaveID[i] = 0;
}
else
{
for(i = 0; i < 6; i++)
accessiblesaveID[i] = 0;
}
fprintf(stdout, "Ext savedata id: 0x%08"PRIx64"\n",extdataID);
for(i = 0; i < 2; i++) for(i = 0; i < 2; i++)
fprintf(stdout, "System savedata id %d: 0x%08x %s\n",i+1,systemsaveID[i],exheader_getvalidstring(ctx->validsystemsaveID[i])); fprintf(stdout, "System savedata id %d: 0x%x %s\n",i+1, ctx->system_local_caps.system_saveid[i],exheader_getvalidstring(ctx->validsystemsaveID[i]));
for(i = 0; i < 3; i++) for(i = 0; i < 3; i++)
fprintf(stdout, "OtherUserSaveDataId%d: 0x%05x\n",i+1,otherusersaveID[i]); fprintf(stdout, "OtherUserSaveDataId%d: 0x%x\n",i+1, ctx->system_local_caps.other_user_saveid[i]);
fprintf(stdout, "Accessible Savedata Ids:\n"); fprintf(stdout, "Accessible Savedata Ids:\n");
for(i = 0; i < 6; i++) for(i = 0; i < 6; i++)
{ {
if(accessiblesaveID[i] != 0x00000) if(ctx->system_local_caps.accessible_saveid[i] != 0x00000)
fprintf(stdout, " > 0x%05x\n",accessiblesaveID[i]); fprintf(stdout, " > 0x%05x\n", ctx->system_local_caps.accessible_saveid[i]);
} }
fprintf(stdout, "Other Variation Saves: %s\n", accessOtherVariationSavedata ? "Accessible" : "Inaccessible"); fprintf(stdout, "Other Variation Saves: %s\n", ctx->system_local_caps.use_other_variation_savedata ? "Accessible" : "Inaccessible");
if(ctx->validaccessinfo == Unchecked) fprintf(stdout, "Access info: 0x%"PRIx64" %s\n", ctx->system_local_caps.accessinfo,exheader_getvalidstring(ctx->validaccessinfo));
memdump(stdout, "Access info: ", ctx->header.arm11systemlocalcaps.storageinfo.accessinfo, 7); exheader_print_arm11accessinfo(ctx);
else if(ctx->validaccessinfo == Good)
memdump(stdout, "Access info (GOOD): ", ctx->header.arm11systemlocalcaps.storageinfo.accessinfo, 7);
else
memdump(stdout, "Access info (FAIL): ", ctx->header.arm11systemlocalcaps.storageinfo.accessinfo, 7);
exheader_print_arm11accessinfo(ctx);
fprintf(stdout, "Other attributes: %02X", ctx->header.arm11systemlocalcaps.storageinfo.otherattributes);
/*
if(otherattibutes & 1)
fprintf(stdout," [no use romfs]");
if(otherattibutes & 2)
fprintf(stdout," [use extended savedata access control]");
*/
printf("\n");
} }
int exheader_signature_verify(exheader_context* ctx, rsakey2048* key) int exheader_signature_verify(exheader_context* ctx, rsakey2048* key)
@@ -486,61 +486,78 @@ int exheader_signature_verify(exheader_context* ctx, rsakey2048* key)
return ctr_rsa_verify_hash(ctx->header.accessdesc.signature, hash, key); return ctr_rsa_verify_hash(ctx->header.accessdesc.signature, hash, key);
} }
void exheader_verify(exheader_context* ctx) void exheader_verify(exheader_context* ctx)
{ {
unsigned int i; unsigned int i, j;
u8 exheaderflag6[3]; exheader_arm11systemlocalcaps_deserialised accessdesc;
u8 descflag6[3];
exheader_deserialise_arm11localcaps_permissions(&accessdesc, &ctx->header.accessdesc.arm11systemlocalcaps);
ctx->validsystemsaveID[0] = Good; ctx->validsystemsaveID[0] = Good;
ctx->validsystemsaveID[1] = Good; ctx->validsystemsaveID[1] = Good;
ctx->validaccessinfo = Good; ctx->validaccessinfo = Good;
ctx->validcoreversion = Good;
ctx->validprogramid = Good; ctx->validprogramid = Good;
ctx->validpriority = Good; ctx->validpriority = Good;
ctx->validaffinitymask = Good; ctx->validaffinitymask = Good;
ctx->valididealprocessor = Good; ctx->valididealprocessor = Good;
ctx->validold3dssystemmode = Good;
ctx->validnew3dssystemmode = Good;
ctx->validenablel2cache = Good;
ctx->validuseadditionalcores = Good;
ctx->validservicecontrol = Good;
for(i=0; i<8; i++) for(i=0; i<8; i++)
{ {
if (0 == (ctx->header.arm11systemlocalcaps.programid[i] & ~ctx->header.accessdesc.arm11systemlocalcaps.programid[i])) if (ctx->system_local_caps.program_id[i] == accessdesc.program_id[i] || accessdesc.program_id[i] == 0xFF)
continue; continue;
ctx->validprogramid = Fail; ctx->validprogramid = Fail;
break; break;
} }
// Ideal Proccessor if (ctx->system_local_caps.core_version != accessdesc.core_version)
exheaderflag6[0] = (ctx->header.arm11systemlocalcaps.flag>>0)&0x3; ctx->validcoreversion = Fail;
descflag6[0] = (ctx->header.accessdesc.arm11systemlocalcaps.flag>>0)&0x3;
// Affinity Mask
exheaderflag6[1] = (ctx->header.arm11systemlocalcaps.flag>>2)&0x3;
descflag6[1] = (ctx->header.accessdesc.arm11systemlocalcaps.flag>>2)&0x3;
// System Mode
//exheaderflag6[2] = (ctx->header.arm11systemlocalcaps.flag>>4)&0xf;
//descflag6[2] = (ctx->header.accessdesc.arm11systemlocalcaps.flag>>4)&0xf;
if (ctx->header.accessdesc.arm11systemlocalcaps.priority > ctx->header.arm11systemlocalcaps.priority || ctx->header.arm11systemlocalcaps.priority > 127) if (ctx->system_local_caps.priority < accessdesc.priority)
ctx->validpriority = Fail; ctx->validpriority = Fail;
if((1<<exheaderflag6[0] & descflag6[0]) == 0) if((1<<ctx->system_local_caps.ideal_processor & accessdesc.ideal_processor) == 0)
ctx->valididealprocessor = Fail; ctx->valididealprocessor = Fail;
if (exheaderflag6[1] & ~descflag6[1]) if (ctx->system_local_caps.affinity_mask & ~accessdesc.affinity_mask)
ctx->validaffinitymask = Fail; ctx->validaffinitymask = Fail;
if (ctx->system_local_caps.old3ds_systemmode > accessdesc.old3ds_systemmode)
ctx->validold3dssystemmode = Fail;
if (ctx->system_local_caps.new3ds_systemmode > accessdesc.new3ds_systemmode)
ctx->validnew3dssystemmode = Fail;
// Storage Info Verify // Storage Info Verify
if(0 != (getle32(ctx->header.arm11systemlocalcaps.storageinfo.systemsavedataid) & ~getle32(ctx->header.accessdesc.arm11systemlocalcaps.storageinfo.systemsavedataid))) if(ctx->system_local_caps.system_saveid[0] & ~accessdesc.system_saveid[0])
ctx->validsystemsaveID[0] = Fail; ctx->validsystemsaveID[0] = Fail;
if(0 != (getle32(ctx->header.arm11systemlocalcaps.storageinfo.systemsavedataid+4) & ~getle32(ctx->header.accessdesc.arm11systemlocalcaps.storageinfo.systemsavedataid+4))) if(ctx->system_local_caps.system_saveid[1] & ~accessdesc.system_saveid[1])
ctx->validsystemsaveID[1] = Fail; ctx->validsystemsaveID[1] = Fail;
for(i=0; i<7; i++)
{ if (ctx->system_local_caps.accessinfo & ~accessdesc.accessinfo)
if(0 == (ctx->header.arm11systemlocalcaps.storageinfo.accessinfo[i] & ~ctx->header.accessdesc.arm11systemlocalcaps.storageinfo.accessinfo[i]))
continue;
ctx->validaccessinfo = Fail; ctx->validaccessinfo = Fail;
break;
// Service Access Control
for (i = 0; i < 34; i++) {
if (strlen(ctx->system_local_caps.service_access_control[i]) == 0)
continue;
for (j = 0; j < 34; j++) {
if (strcmp(ctx->system_local_caps.service_access_control[i], accessdesc.service_access_control[j]) == 0)
break;
}
if (strcmp(ctx->system_local_caps.service_access_control[i], accessdesc.service_access_control[j]) == 0)
continue;
ctx->validservicecontrol = Fail;
} }
if (ctx->usersettings) if (ctx->usersettings)
@@ -609,21 +626,21 @@ void exheader_print(exheader_context* ctx)
fprintf(stdout, "Program id: %016"PRIx64" %s\n", getle64(ctx->header.arm11systemlocalcaps.programid), exheader_getvalidstring(ctx->validprogramid)); fprintf(stdout, "Program id: %016"PRIx64" %s\n", getle64(ctx->header.arm11systemlocalcaps.programid), exheader_getvalidstring(ctx->validprogramid));
fprintf(stdout, "Core version: 0x%X\n", getle32(ctx->header.arm11systemlocalcaps.coreversion)); fprintf(stdout, "Core version: 0x%X\n", getle32(ctx->header.arm11systemlocalcaps.coreversion));
fprintf(stdout, "System mode: 0x%X\n", (ctx->header.arm11systemlocalcaps.flag>>4)&0xF); fprintf(stdout, "System mode: %d %s\n", ctx->system_local_caps.old3ds_systemmode, exheader_getvalidstring(ctx->validold3dssystemmode));
fprintf(stdout, "Ideal processor: %d %s\n", (ctx->header.arm11systemlocalcaps.flag>>0)&0x3, exheader_getvalidstring(ctx->valididealprocessor)); fprintf(stdout, "System mode (New3DS): %d %s\n", ctx->system_local_caps.new3ds_systemmode, exheader_getvalidstring(ctx->validnew3dssystemmode));
fprintf(stdout, "Affinity mask: %d %s\n", (ctx->header.arm11systemlocalcaps.flag>>2)&0x3, exheader_getvalidstring(ctx->validaffinitymask)); fprintf(stdout, "Ideal processor: %d %s\n", ctx->system_local_caps.ideal_processor, exheader_getvalidstring(ctx->valididealprocessor));
fprintf(stdout, "Main thread priority: %d %s\n", ctx->header.arm11systemlocalcaps.priority, exheader_getvalidstring(ctx->validpriority)); fprintf(stdout, "Affinity mask: %d %s\n", ctx->system_local_caps.affinity_mask, exheader_getvalidstring(ctx->validaffinitymask));
fprintf(stdout, "Main thread priority: %d %s\n", ctx->system_local_caps.priority, exheader_getvalidstring(ctx->validpriority));
// print resource limit descriptor too? currently mostly zeroes... // print resource limit descriptor too? currently mostly zeroes...
exheader_print_arm11storageinfo(ctx); exheader_print_arm11storageinfo(ctx);
exheader_print_arm11kernelcapabilities(ctx); exheader_print_arm11kernelcapabilities(ctx);
exheader_print_arm9accesscontrol(ctx); exheader_print_arm9accesscontrol(ctx);
fprintf(stdout, "Service access: %s\n", exheader_getvalidstring(ctx->validservicecontrol));
for(i=0; i<34; i++)
for(i=0; i<0x20; i++)
{ {
if (getle64(ctx->header.arm11systemlocalcaps.serviceaccesscontrol[i]) != 0x0000000000000000UL) if (strlen(ctx->system_local_caps.service_access_control[i]) > 0)
fprintf(stdout, "Service access: %.8s\n", ctx->header.arm11systemlocalcaps.serviceaccesscontrol[i]); fprintf(stdout, " > %s\n", ctx->system_local_caps.service_access_control[i]);
} }
fprintf(stdout, "Reslimit category: %02X\n", ctx->header.arm11systemlocalcaps.resourcelimitcategory); fprintf(stdout, "Reslimit category: %02X\n", ctx->header.arm11systemlocalcaps.resourcelimitcategory);
} }
+39 -5
View File
@@ -57,16 +57,41 @@ typedef struct
{ {
u8 programid[8]; u8 programid[8];
u8 coreversion[4]; u8 coreversion[4];
u8 reserved0[2]; u8 flag[4];
u8 flag;
u8 priority;
u8 resourcelimitdescriptor[0x10][2]; u8 resourcelimitdescriptor[0x10][2];
exheader_storageinfo storageinfo; exheader_storageinfo storageinfo;
u8 serviceaccesscontrol[0x20][8]; u8 serviceaccesscontrol[34][8];
u8 reserved[0x1f]; u8 reserved[0xf];
u8 resourcelimitcategory; u8 resourcelimitcategory;
} exheader_arm11systemlocalcaps; } exheader_arm11systemlocalcaps;
typedef struct
{
u8 program_id[8];
u32 core_version;
// flag
u8 enable_l2_cache;
u8 use_additional_cores;
u8 new3ds_systemmode;
u8 ideal_processor;
u8 affinity_mask;
u8 old3ds_systemmode;
s8 priority;
// storageinfo
u64 extdata_id;
u32 other_user_saveid[3];
u8 use_other_variation_savedata;
u32 accessible_saveid[3];
u32 system_saveid[2];
u64 accessinfo;
char service_access_control[34][10];
u8 resource_limit_category;
} exheader_arm11systemlocalcaps_deserialised;
typedef struct typedef struct
{ {
u8 descriptors[28][4]; u8 descriptors[28][4];
@@ -115,6 +140,9 @@ typedef struct
u32 offset; u32 offset;
u32 size; u32 size;
exheader_header header; exheader_header header;
exheader_arm11systemlocalcaps_deserialised system_local_caps;
ctr_aes_context aes; ctr_aes_context aes;
ctr_rsa_context rsa; ctr_rsa_context rsa;
int compressedflag; int compressedflag;
@@ -123,8 +151,14 @@ typedef struct
int validpriority; int validpriority;
int validaffinitymask; int validaffinitymask;
int valididealprocessor; int valididealprocessor;
int validold3dssystemmode;
int validnew3dssystemmode;
int validenablel2cache;
int validuseadditionalcores;
int validcoreversion;
int validsystemsaveID[2]; int validsystemsaveID[2];
int validaccessinfo; int validaccessinfo;
int validservicecontrol;
int validsignature; int validsignature;
} exheader_context; } exheader_context;
+14 -7
View File
@@ -540,6 +540,17 @@ static const char* contenttypetostring(unsigned char flags)
case 2: return "Manual"; case 2: return "Manual";
case 3: return "Child"; case 3: return "Child";
case 4: return "Trial"; case 4: return "Trial";
case 5: return "Extended System Update";
default: return "Unknown";
}
}
static const char* contentplatformtostring(unsigned char platform)
{
switch (platform)
{
case 1: return "CTR";
case 2: return "SNAKE";
default: return "Unknown"; default: return "Unknown";
} }
} }
@@ -566,6 +577,7 @@ void ncch_print(ncch_context* ctx)
fprintf(stdout, "Partition id: %016"PRIx64"\n", getle64(header->partitionid)); fprintf(stdout, "Partition id: %016"PRIx64"\n", getle64(header->partitionid));
fprintf(stdout, "Maker code: %04x\n", getle16(header->makercode)); fprintf(stdout, "Maker code: %04x\n", getle16(header->makercode));
fprintf(stdout, "Version: %04x\n", getle16(header->version)); fprintf(stdout, "Version: %04x\n", getle16(header->version));
fprintf(stdout, "Title seed check: %08x\n", getle32(header->seedcheck));
fprintf(stdout, "Program id: %016"PRIx64"\n", getle64(header->programid)); fprintf(stdout, "Program id: %016"PRIx64"\n", getle64(header->programid));
if(ctx->logohashcheck == Unchecked) if(ctx->logohashcheck == Unchecked)
memdump(stdout, "Logo hash: ", header->logohash, 0x20); memdump(stdout, "Logo hash: ", header->logohash, 0x20);
@@ -587,16 +599,11 @@ void ncch_print(ncch_context* ctx)
fprintf(stdout, " > Crypto key: None\n"); fprintf(stdout, " > Crypto key: None\n");
else if (header->flags[7] & 1) else if (header->flags[7] & 1)
fprintf(stdout, " > Crypto key: %s\n", programid_is_system(header->programid)? "Fixed":"Zeros"); fprintf(stdout, " > Crypto key: %s\n", programid_is_system(header->programid)? "Fixed":"Zeros");
else if (header->flags[3] & 1)
fprintf(stdout, " > Crypto key: Secure2\n");
else if (header->flags[3] & 10)
fprintf(stdout, " > Crypto key: secure3 (New 3DS)\n");
else else
fprintf(stdout, " > Crypto key: Secure\n"); fprintf(stdout, " > Crypto key: Secure (%d)%s\n", header->flags[3], header->flags[7] & 32? " (KeyY seeded)" : "");
fprintf(stdout, " > Form type: %s\n", formtypetostring(header->flags[5])); fprintf(stdout, " > Form type: %s\n", formtypetostring(header->flags[5]));
fprintf(stdout, " > Content type: %s\n", contenttypetostring(header->flags[5])); fprintf(stdout, " > Content type: %s\n", contenttypetostring(header->flags[5]));
if (header->flags[4] & 1) fprintf(stdout, " > Content platform: %s\n", contentplatformtostring(header->flags[4]));
fprintf(stdout, " > Content platform: CTR\n");
if (header->flags[7] & 2) if (header->flags[7] & 2)
fprintf(stdout, " > No RomFS mount\n"); fprintf(stdout, " > No RomFS mount\n");
+1 -1
View File
@@ -26,7 +26,7 @@ typedef struct
u8 partitionid[8]; u8 partitionid[8];
u8 makercode[2]; u8 makercode[2];
u8 version[2]; u8 version[2];
u8 reserved0[4]; u8 seedcheck[4];
u8 programid[8]; u8 programid[8];
u8 reserved1[0x10]; u8 reserved1[0x10];
u8 logohash[0x20]; u8 logohash[0x20];