mirror of
https://github.com/jakcron/nstool
synced 2024-12-25 14:11:14 +00:00
[nstool] Refactor logic for managing output mode.
This commit is contained in:
parent
17cc0d9c47
commit
2f5a4d9c23
24 changed files with 436 additions and 416 deletions
|
@ -7,7 +7,7 @@
|
|||
AssetProcess::AssetProcess() :
|
||||
mFile(nullptr),
|
||||
mOwnIFile(false),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||
mVerify(false)
|
||||
{
|
||||
|
||||
|
@ -29,7 +29,8 @@ void AssetProcess::process()
|
|||
}
|
||||
|
||||
importHeader();
|
||||
displayHeader();
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||
displayHeader();
|
||||
processSections();
|
||||
}
|
||||
|
||||
|
@ -39,9 +40,9 @@ void AssetProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
|||
mOwnIFile = ownIFile;
|
||||
}
|
||||
|
||||
void AssetProcess::setCliOutputMode(CliOutputType type)
|
||||
void AssetProcess::setCliOutputMode(CliOutputMode type)
|
||||
{
|
||||
mCliOutputType = type;
|
||||
mCliOutputMode = type;
|
||||
}
|
||||
|
||||
void AssetProcess::setVerifyMode(bool verify)
|
||||
|
@ -117,7 +118,7 @@ void AssetProcess::processSections()
|
|||
}
|
||||
|
||||
mNacp.setInputFile(new OffsetAdjustedIFile(mFile, false, mHdr.getNacpInfo().offset, mHdr.getNacpInfo().size), true);
|
||||
mNacp.setCliOutputMode(mCliOutputType);
|
||||
mNacp.setCliOutputMode(mCliOutputMode);
|
||||
mNacp.setVerifyMode(mVerify);
|
||||
|
||||
mNacp.process();
|
||||
|
@ -129,7 +130,7 @@ void AssetProcess::processSections()
|
|||
throw fnd::Exception(kModuleName, "ASET geometry for romfs beyond file size");
|
||||
|
||||
mRomfs.setInputFile(new OffsetAdjustedIFile(mFile, false, mHdr.getRomfsInfo().offset, mHdr.getRomfsInfo().size), true);
|
||||
mRomfs.setCliOutputMode(mCliOutputType);
|
||||
mRomfs.setCliOutputMode(mCliOutputMode);
|
||||
mRomfs.setVerifyMode(mVerify);
|
||||
|
||||
mRomfs.process();
|
||||
|
@ -138,7 +139,7 @@ void AssetProcess::processSections()
|
|||
|
||||
void AssetProcess::displayHeader()
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT))
|
||||
{
|
||||
printf("[ASET Header]\n");
|
||||
printf(" Icon:\n");
|
||||
|
|
|
@ -17,7 +17,7 @@ public:
|
|||
void process();
|
||||
|
||||
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setCliOutputMode(CliOutputMode type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
void setListFs(bool list);
|
||||
|
@ -32,7 +32,7 @@ private:
|
|||
|
||||
fnd::IFile* mFile;
|
||||
bool mOwnIFile;
|
||||
CliOutputType mCliOutputType;
|
||||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
sOptional<std::string> mIconExtractPath;
|
||||
|
|
|
@ -145,7 +145,7 @@ void CnmtProcess::displayCmnt()
|
|||
CnmtProcess::CnmtProcess() :
|
||||
mFile(nullptr),
|
||||
mOwnIFile(false),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||
mVerify(false)
|
||||
{
|
||||
}
|
||||
|
@ -172,10 +172,8 @@ void CnmtProcess::process()
|
|||
|
||||
mCnmt.importBinary(scratch.getBytes(), scratch.getSize());
|
||||
|
||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||
{
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||
displayCmnt();
|
||||
}
|
||||
}
|
||||
|
||||
void CnmtProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
||||
|
@ -184,9 +182,9 @@ void CnmtProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
|||
mOwnIFile = ownIFile;
|
||||
}
|
||||
|
||||
void CnmtProcess::setCliOutputMode(CliOutputType type)
|
||||
void CnmtProcess::setCliOutputMode(CliOutputMode type)
|
||||
{
|
||||
mCliOutputType = type;
|
||||
mCliOutputMode = type;
|
||||
}
|
||||
|
||||
void CnmtProcess::setVerifyMode(bool verify)
|
||||
|
|
|
@ -15,7 +15,7 @@ public:
|
|||
void process();
|
||||
|
||||
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setCliOutputMode(CliOutputMode type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
const nx::ContentMetaBinary& getContentMetaBinary() const;
|
||||
|
@ -25,7 +25,7 @@ private:
|
|||
|
||||
fnd::IFile* mFile;
|
||||
bool mOwnIFile;
|
||||
CliOutputType mCliOutputType;
|
||||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
nx::ContentMetaBinary mCnmt;
|
||||
|
|
|
@ -426,7 +426,7 @@ std::string getSaveDataSizeStr(int64_t size)
|
|||
NacpProcess::NacpProcess() :
|
||||
mFile(nullptr),
|
||||
mOwnIFile(false),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||
mVerify(false)
|
||||
{
|
||||
}
|
||||
|
@ -453,10 +453,8 @@ void NacpProcess::process()
|
|||
|
||||
mNacp.importBinary(scratch.getBytes(), scratch.getSize());
|
||||
|
||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||
{
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||
displayNacp();
|
||||
}
|
||||
}
|
||||
|
||||
void NacpProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
||||
|
@ -465,9 +463,9 @@ void NacpProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
|||
mOwnIFile = ownIFile;
|
||||
}
|
||||
|
||||
void NacpProcess::setCliOutputMode(CliOutputType type)
|
||||
void NacpProcess::setCliOutputMode(CliOutputMode type)
|
||||
{
|
||||
mCliOutputType = type;
|
||||
mCliOutputMode = type;
|
||||
}
|
||||
|
||||
void NacpProcess::setVerifyMode(bool verify)
|
||||
|
@ -485,7 +483,7 @@ void NacpProcess::displayNacp()
|
|||
printf("[ApplicationControlProperty]\n");
|
||||
printf(" Menu Description:\n");
|
||||
printf(" DisplayVersion: %s\n", mNacp.getDisplayVersion().c_str());
|
||||
if (mNacp.getIsbn().empty() == false)
|
||||
if (mNacp.getIsbn().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
printf(" ISBN: %s\n", mNacp.getIsbn().c_str());
|
||||
for (size_t i = 0; i < mNacp.getTitle().getSize(); i++)
|
||||
{
|
||||
|
@ -520,7 +518,7 @@ void NacpProcess::displayNacp()
|
|||
printf(" Age: %d\n", mNacp.getRatingAge()[i].age);
|
||||
}
|
||||
|
||||
if (mNacp.getBcatPassphase().empty() == false)
|
||||
if (mNacp.getBcatPassphase().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" BCAT:\n");
|
||||
printf(" BcatPassphase: %s\n", mNacp.getBcatPassphase().c_str());
|
||||
|
@ -537,35 +535,35 @@ void NacpProcess::displayNacp()
|
|||
}
|
||||
printf(" SaveData:\n");
|
||||
printf(" SaveDatawOwnerId: 0x%016" PRIx64 "\n", mNacp.getSaveDatawOwnerId());
|
||||
if (mNacp.getUserAccountSaveDataSize().journal_size > 0)
|
||||
if (mNacp.getUserAccountSaveDataSize().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" UserAccountSaveData:\n");
|
||||
printf(" Size: %s\n", getSaveDataSizeStr(mNacp.getUserAccountSaveDataSize().size).c_str());
|
||||
printf(" JournalSize: %s\n", getSaveDataSizeStr(mNacp.getUserAccountSaveDataSize().journal_size).c_str());
|
||||
}
|
||||
if (mNacp.getDeviceSaveDataSize().journal_size > 0)
|
||||
if (mNacp.getDeviceSaveDataSize().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" DeviceSaveData:\n");
|
||||
printf(" Size: %s\n", getSaveDataSizeStr(mNacp.getDeviceSaveDataSize().size).c_str());
|
||||
printf(" JournalSize: %s\n", getSaveDataSizeStr(mNacp.getDeviceSaveDataSize().journal_size).c_str());
|
||||
}
|
||||
if (mNacp.getUserAccountSaveDataMax().journal_size > 0)
|
||||
if (mNacp.getUserAccountSaveDataMax().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" UserAccountSaveDataMax:\n");
|
||||
printf(" Size: %s\n", getSaveDataSizeStr(mNacp.getUserAccountSaveDataMax().size).c_str());
|
||||
printf(" JournalSize: %s\n", getSaveDataSizeStr(mNacp.getUserAccountSaveDataMax().journal_size).c_str());
|
||||
}
|
||||
if (mNacp.getDeviceSaveDataMax().journal_size > 0)
|
||||
if (mNacp.getDeviceSaveDataMax().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" DeviceSaveDataMax:\n");
|
||||
printf(" Size: %s\n", getSaveDataSizeStr(mNacp.getDeviceSaveDataMax().size).c_str());
|
||||
printf(" JournalSize: %s\n", getSaveDataSizeStr(mNacp.getDeviceSaveDataMax().journal_size).c_str());
|
||||
}
|
||||
if (mNacp.getTemporaryStorageSize() > 0)
|
||||
if (mNacp.getTemporaryStorageSize() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" TemporaryStorageSize: %s\n", getSaveDataSizeStr(mNacp.getTemporaryStorageSize()).c_str());
|
||||
}
|
||||
if (mNacp.getCacheStorageSize().journal_size > 0)
|
||||
if (mNacp.getCacheStorageSize().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" CacheStorage:\n");
|
||||
printf(" Size: %s\n", getSaveDataSizeStr(mNacp.getCacheStorageSize().size).c_str());
|
||||
|
@ -575,7 +573,10 @@ void NacpProcess::displayNacp()
|
|||
}
|
||||
printf(" Other Flags:\n");
|
||||
printf(" StartupUserAccount: %s\n", getStartupUserAccountStr(mNacp.getStartupUserAccount()));
|
||||
//printf(" TouchScreenUsageMode: %s\n", getTouchScreenUsageModeStr(mNacp.getTouchScreenUsageMode()));
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" TouchScreenUsageMode: %s\n", getTouchScreenUsageModeStr(mNacp.getTouchScreenUsageMode()));
|
||||
}
|
||||
printf(" AttributeFlag: %s\n", getAttributeFlagStr(mNacp.getAttributeFlag()));
|
||||
printf(" CrashReportMode: %s\n", getCrashReportModeStr(mNacp.getCrashReportMode()));
|
||||
printf(" HDCP: %s\n", getHdcpStr(mNacp.getHdcp()));
|
||||
|
@ -584,16 +585,16 @@ void NacpProcess::displayNacp()
|
|||
printf(" DataLossConfirmation: %s\n", getDataLossConfirmationStr(mNacp.getDataLossConfirmation()));
|
||||
printf(" RepairFlag: %s\n", getRepairFlagStr(mNacp.getRepairFlag()));
|
||||
printf(" ProgramIndex: 0x%02x\n", mNacp.getProgramIndex());
|
||||
if (mNacp.getApplicationErrorCodeCategory().empty() == false)
|
||||
if (mNacp.getApplicationErrorCodeCategory().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" ApplicationErrorCodeCategory: %s\n", mNacp.getApplicationErrorCodeCategory().c_str());
|
||||
}
|
||||
if (mNacp.getSeedForPsuedoDeviceId() > 0 || mNacp.getPresenceGroupId() > 0)
|
||||
if (mNacp.getSeedForPsuedoDeviceId() > 0 || mNacp.getPresenceGroupId() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" Other Ids:\n");
|
||||
if (mNacp.getSeedForPsuedoDeviceId() > 0)
|
||||
if (mNacp.getSeedForPsuedoDeviceId() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
printf(" SeedForPsuedoDeviceId: 0x%016" PRIx64 "\n", mNacp.getSeedForPsuedoDeviceId());
|
||||
if (mNacp.getPresenceGroupId() > 0)
|
||||
if (mNacp.getPresenceGroupId() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
printf(" PresenceGroupId: 0x%016" PRIx64 "\n", mNacp.getPresenceGroupId());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ public:
|
|||
void process();
|
||||
|
||||
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setCliOutputMode(CliOutputMode type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
const nx::ApplicationControlPropertyBinary& getApplicationControlPropertyBinary() const;
|
||||
|
@ -25,7 +25,7 @@ private:
|
|||
|
||||
fnd::IFile* mFile;
|
||||
bool mOwnIFile;
|
||||
CliOutputType mCliOutputType;
|
||||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
nx::ApplicationControlPropertyBinary mNacp;
|
||||
|
|
|
@ -224,7 +224,7 @@ NcaProcess::NcaProcess() :
|
|||
mFile(nullptr),
|
||||
mOwnIFile(false),
|
||||
mKeyset(nullptr),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||
mVerify(false),
|
||||
mListFs(false)
|
||||
{
|
||||
|
@ -283,7 +283,7 @@ void NcaProcess::process()
|
|||
validateNcaSignatures();
|
||||
|
||||
// display header
|
||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||
displayHeader();
|
||||
|
||||
// process partition
|
||||
|
@ -322,9 +322,9 @@ void NcaProcess::setKeyset(const sKeyset* keyset)
|
|||
mKeyset = keyset;
|
||||
}
|
||||
|
||||
void NcaProcess::setCliOutputMode(CliOutputType type)
|
||||
void NcaProcess::setCliOutputMode(CliOutputMode type)
|
||||
{
|
||||
mCliOutputType = type;
|
||||
mCliOutputMode = type;
|
||||
}
|
||||
|
||||
void NcaProcess::setVerifyMode(bool verify)
|
||||
|
@ -458,21 +458,27 @@ void NcaProcess::generateNcaBodyEncryptionKeys()
|
|||
{
|
||||
mBodyKeys.aes_xts = mKeyset->nca.manual_body_key_aesxts;
|
||||
}
|
||||
/*
|
||||
if (mBodyKeys.aes_ctr.isSet)
|
||||
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_KEY_DATA))
|
||||
{
|
||||
printf("AES-CTR Key: ");
|
||||
fnd::SimpleTextOutput::hexDump(mBodyKeys.aes_ctr.var.key, sizeof(mBodyKeys.aes_ctr.var));
|
||||
if (mBodyKeys.aes_ctr.isSet)
|
||||
{
|
||||
printf("[NCA Body Key]\n");
|
||||
printf(" AES-CTR Key: ");
|
||||
fnd::SimpleTextOutput::hexDump(mBodyKeys.aes_ctr.var.key, sizeof(mBodyKeys.aes_ctr.var));
|
||||
}
|
||||
|
||||
if (mBodyKeys.aes_xts.isSet)
|
||||
{
|
||||
printf("[NCA Body Key]\n");
|
||||
printf(" AES-XTS Key0: ");
|
||||
fnd::SimpleTextOutput::hexDump(mBodyKeys.aes_xts.var.key[0], sizeof(mBodyKeys.aes_ctr.var));
|
||||
printf(" AES-XTS Key1: ");
|
||||
fnd::SimpleTextOutput::hexDump(mBodyKeys.aes_xts.var.key[1], sizeof(mBodyKeys.aes_ctr.var));
|
||||
}
|
||||
}
|
||||
|
||||
if (mBodyKeys.aes_xts.isSet)
|
||||
{
|
||||
printf("AES-XTS Key0: ");
|
||||
fnd::SimpleTextOutput::hexDump(mBodyKeys.aes_xts.var.key[0], sizeof(mBodyKeys.aes_ctr.var));
|
||||
printf("AES-XTS Key1: ");
|
||||
fnd::SimpleTextOutput::hexDump(mBodyKeys.aes_xts.var.key[1], sizeof(mBodyKeys.aes_ctr.var));
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
void NcaProcess::generatePartitionConfiguration()
|
||||
|
@ -590,9 +596,7 @@ void NcaProcess::validateNcaSignatures()
|
|||
// validate signature[0]
|
||||
if (crypto::rsa::pss::rsaVerify(mKeyset->nca.header_sign_key, crypto::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_main) != 0)
|
||||
{
|
||||
// this is minimal even though it's a warning because it's a validation method
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] NCA Header Main Signature: FAIL \n");
|
||||
printf("[WARNING] NCA Header Main Signature: FAIL \n");
|
||||
}
|
||||
|
||||
// validate signature[1]
|
||||
|
@ -604,7 +608,7 @@ void NcaProcess::validateNcaSignatures()
|
|||
{
|
||||
PfsProcess exefs;
|
||||
exefs.setInputFile(mPartitions[nx::nca::PARTITION_CODE].reader, SHARED_IFILE);
|
||||
exefs.setCliOutputMode(OUTPUT_MINIMAL);
|
||||
exefs.setCliOutputMode(0);
|
||||
exefs.process();
|
||||
|
||||
// open main.npdm
|
||||
|
@ -614,38 +618,30 @@ void NcaProcess::validateNcaSignatures()
|
|||
|
||||
NpdmProcess npdm;
|
||||
npdm.setInputFile(new OffsetAdjustedIFile(mPartitions[nx::nca::PARTITION_CODE].reader, SHARED_IFILE, file.offset, file.size), OWN_IFILE);
|
||||
npdm.setCliOutputMode(OUTPUT_MINIMAL);
|
||||
npdm.setCliOutputMode(0);
|
||||
npdm.process();
|
||||
|
||||
if (crypto::rsa::pss::rsaVerify(npdm.getNpdmBinary().getAcid().getNcaHeader2RsaKey(), crypto::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_acid) != 0)
|
||||
{
|
||||
// this is minimal even though it's a warning because it's a validation method
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] NCA Header ACID Signature: FAIL \n");
|
||||
printf("[WARNING] NCA Header ACID Signature: FAIL \n");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is minimal even though it's a warning because it's a validation method
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] NCA Header ACID Signature: FAIL (\"%s\" not present in ExeFs)\n", kNpdmExefsPath.c_str());
|
||||
printf("[WARNING] NCA Header ACID Signature: FAIL (\"%s\" not present in ExeFs)\n", kNpdmExefsPath.c_str());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is minimal even though it's a warning because it's a validation method
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] NCA Header ACID Signature: FAIL (ExeFs unreadable)\n");
|
||||
printf("[WARNING] NCA Header ACID Signature: FAIL (ExeFs unreadable)\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is minimal even though it's a warning because it's a validation method
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] NCA Header ACID Signature: FAIL (No ExeFs partition)\n");
|
||||
printf("[WARNING] NCA Header ACID Signature: FAIL (No ExeFs partition)\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -674,7 +670,7 @@ void NcaProcess::displayHeader()
|
|||
}
|
||||
|
||||
|
||||
if (mBodyKeys.keak_list.getSize() > 0)
|
||||
if (mBodyKeys.keak_list.getSize() > 0 && _HAS_BIT(mCliOutputMode, OUTPUT_KEY_DATA))
|
||||
{
|
||||
printf(" Key Area: \n");
|
||||
printf(" <--------------------------------------------------------------------------->\n");
|
||||
|
@ -699,70 +695,74 @@ void NcaProcess::displayHeader()
|
|||
printf(" <--------------------------------------------------------------------------->\n");
|
||||
}
|
||||
|
||||
printf(" Partitions:\n");
|
||||
for (size_t i = 0; i < mHdr.getPartitions().getSize(); i++)
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT))
|
||||
{
|
||||
sPartitionInfo& info = mPartitions[i];
|
||||
printf(" Partitions:\n");
|
||||
for (size_t i = 0; i < mHdr.getPartitions().getSize(); i++)
|
||||
{
|
||||
sPartitionInfo& info = mPartitions[i];
|
||||
|
||||
printf(" %d:\n", (int)i);
|
||||
printf(" Offset: 0x%" PRIx64 "\n", (uint64_t)info.offset);
|
||||
printf(" Size: 0x%" PRIx64 "\n", (uint64_t)info.size);
|
||||
printf(" Format Type: %s\n", getFormatTypeStr(info.format_type));
|
||||
printf(" Hash Type: %s\n", getHashTypeStr(info.hash_type));
|
||||
printf(" Enc. Type: %s\n", getEncryptionTypeStr(info.enc_type));
|
||||
if (info.enc_type == nx::nca::CRYPT_AESCTR)
|
||||
{
|
||||
printf(" AES-CTR: ");
|
||||
crypto::aes::sAesIvCtr ctr;
|
||||
crypto::aes::AesIncrementCounter(info.aes_ctr.iv, info.offset>>4, ctr.iv);
|
||||
fnd::SimpleTextOutput::hexDump(ctr.iv, sizeof(crypto::aes::sAesIvCtr));
|
||||
}
|
||||
if (info.hash_type == nx::nca::HASH_HIERARCHICAL_INTERGRITY)
|
||||
{
|
||||
HashTreeMeta& hash_hdr = info.hash_tree_meta;
|
||||
printf(" HierarchicalIntegrity Header:\n");
|
||||
//printf(" TypeId: 0x%x\n", hash_hdr.type_id.get());
|
||||
//printf(" MasterHashSize: 0x%x\n", hash_hdr.master_hash_size.get());
|
||||
//printf(" LayerNum: %d\n", hash_hdr.getLayerInfo().getSize());
|
||||
for (size_t j = 0; j < hash_hdr.getHashLayerInfo().getSize(); j++)
|
||||
printf(" %d:\n", (int)i);
|
||||
printf(" Offset: 0x%" PRIx64 "\n", (uint64_t)info.offset);
|
||||
printf(" Size: 0x%" PRIx64 "\n", (uint64_t)info.size);
|
||||
printf(" Format Type: %s\n", getFormatTypeStr(info.format_type));
|
||||
printf(" Hash Type: %s\n", getHashTypeStr(info.hash_type));
|
||||
printf(" Enc. Type: %s\n", getEncryptionTypeStr(info.enc_type));
|
||||
if (info.enc_type == nx::nca::CRYPT_AESCTR)
|
||||
{
|
||||
printf(" Hash Layer %d:\n", (int)j);
|
||||
printf(" Offset: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getHashLayerInfo()[j].offset);
|
||||
printf(" Size: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getHashLayerInfo()[j].size);
|
||||
printf(" BlockSize: 0x%" PRIx32 "\n", (uint32_t)hash_hdr.getHashLayerInfo()[j].block_size);
|
||||
printf(" AES-CTR: ");
|
||||
crypto::aes::sAesIvCtr ctr;
|
||||
crypto::aes::AesIncrementCounter(info.aes_ctr.iv, info.offset>>4, ctr.iv);
|
||||
fnd::SimpleTextOutput::hexDump(ctr.iv, sizeof(crypto::aes::sAesIvCtr));
|
||||
}
|
||||
if (info.hash_type == nx::nca::HASH_HIERARCHICAL_INTERGRITY)
|
||||
{
|
||||
HashTreeMeta& hash_hdr = info.hash_tree_meta;
|
||||
printf(" HierarchicalIntegrity Header:\n");
|
||||
//printf(" TypeId: 0x%x\n", hash_hdr.type_id.get());
|
||||
//printf(" MasterHashSize: 0x%x\n", hash_hdr.master_hash_size.get());
|
||||
//printf(" LayerNum: %d\n", hash_hdr.getLayerInfo().getSize());
|
||||
for (size_t j = 0; j < hash_hdr.getHashLayerInfo().getSize(); j++)
|
||||
{
|
||||
printf(" Hash Layer %d:\n", (int)j);
|
||||
printf(" Offset: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getHashLayerInfo()[j].offset);
|
||||
printf(" Size: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getHashLayerInfo()[j].size);
|
||||
printf(" BlockSize: 0x%" PRIx32 "\n", (uint32_t)hash_hdr.getHashLayerInfo()[j].block_size);
|
||||
}
|
||||
|
||||
printf(" Data Layer:\n");
|
||||
printf(" Offset: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getDataLayer().offset);
|
||||
printf(" Size: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getDataLayer().size);
|
||||
printf(" BlockSize: 0x%" PRIx32 "\n", (uint32_t)hash_hdr.getDataLayer().block_size);
|
||||
for (size_t j = 0; j < hash_hdr.getMasterHashList().getSize(); j++)
|
||||
{
|
||||
printf(" Master Hash %d: ", (int)j);
|
||||
fnd::SimpleTextOutput::hexDump(hash_hdr.getMasterHashList()[j].bytes, sizeof(crypto::sha::sSha256Hash));
|
||||
printf(" Data Layer:\n");
|
||||
printf(" Offset: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getDataLayer().offset);
|
||||
printf(" Size: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getDataLayer().size);
|
||||
printf(" BlockSize: 0x%" PRIx32 "\n", (uint32_t)hash_hdr.getDataLayer().block_size);
|
||||
for (size_t j = 0; j < hash_hdr.getMasterHashList().getSize(); j++)
|
||||
{
|
||||
printf(" Master Hash %d: ", (int)j);
|
||||
fnd::SimpleTextOutput::hexDump(hash_hdr.getMasterHashList()[j].bytes, sizeof(crypto::sha::sSha256Hash));
|
||||
}
|
||||
}
|
||||
else if (info.hash_type == nx::nca::HASH_HIERARCHICAL_SHA256)
|
||||
{
|
||||
HashTreeMeta& hash_hdr = info.hash_tree_meta;
|
||||
printf(" HierarchicalSha256 Header:\n");
|
||||
printf(" Master Hash: ");
|
||||
fnd::SimpleTextOutput::hexDump(hash_hdr.getMasterHashList()[0].bytes, sizeof(crypto::sha::sSha256Hash));
|
||||
printf(" HashBlockSize: 0x%" PRIx32 "\n", (uint32_t)hash_hdr.getDataLayer().block_size);
|
||||
//printf(" LayerNum: %d\n", hash_hdr.getLayerInfo().getSize());
|
||||
printf(" Hash Layer:\n");
|
||||
printf(" Offset: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getHashLayerInfo()[0].offset);
|
||||
printf(" Size: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getHashLayerInfo()[0].size);
|
||||
printf(" Data Layer:\n");
|
||||
printf(" Offset: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getDataLayer().offset);
|
||||
printf(" Size: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getDataLayer().size);
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// printf(" Hash Superblock:\n");
|
||||
// fnd::SimpleTextOutput::hxdStyleDump(fs_header.hash_superblock, nx::nca::kFsHeaderHashSuperblockLen);
|
||||
//}
|
||||
}
|
||||
else if (info.hash_type == nx::nca::HASH_HIERARCHICAL_SHA256)
|
||||
{
|
||||
HashTreeMeta& hash_hdr = info.hash_tree_meta;
|
||||
printf(" HierarchicalSha256 Header:\n");
|
||||
printf(" Master Hash: ");
|
||||
fnd::SimpleTextOutput::hexDump(hash_hdr.getMasterHashList()[0].bytes, sizeof(crypto::sha::sSha256Hash));
|
||||
printf(" HashBlockSize: 0x%" PRIx32 "\n", (uint32_t)hash_hdr.getDataLayer().block_size);
|
||||
//printf(" LayerNum: %d\n", hash_hdr.getLayerInfo().getSize());
|
||||
printf(" Hash Layer:\n");
|
||||
printf(" Offset: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getHashLayerInfo()[0].offset);
|
||||
printf(" Size: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getHashLayerInfo()[0].size);
|
||||
printf(" Data Layer:\n");
|
||||
printf(" Offset: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getDataLayer().offset);
|
||||
printf(" Size: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getDataLayer().size);
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// printf(" Hash Superblock:\n");
|
||||
// fnd::SimpleTextOutput::hxdStyleDump(fs_header.hash_superblock, nx::nca::kFsHeaderHashSuperblockLen);
|
||||
//}
|
||||
}
|
||||
|
||||
#undef _HEXDUMP_U
|
||||
#undef _HEXDUMP_L
|
||||
}
|
||||
|
@ -791,7 +791,7 @@ void NcaProcess::processPartitions()
|
|||
{
|
||||
PfsProcess pfs;
|
||||
pfs.setInputFile(partition.reader, SHARED_IFILE);
|
||||
pfs.setCliOutputMode(mCliOutputType);
|
||||
pfs.setCliOutputMode(mCliOutputMode);
|
||||
pfs.setListFs(mListFs);
|
||||
if (mHdr.getContentType() == nx::nca::TYPE_PROGRAM)
|
||||
{
|
||||
|
@ -812,7 +812,7 @@ void NcaProcess::processPartitions()
|
|||
{
|
||||
RomfsProcess romfs;
|
||||
romfs.setInputFile(partition.reader, SHARED_IFILE);
|
||||
romfs.setCliOutputMode(mCliOutputType);
|
||||
romfs.setCliOutputMode(mCliOutputMode);
|
||||
romfs.setListFs(mListFs);
|
||||
if (mHdr.getContentType() == nx::nca::TYPE_PROGRAM)
|
||||
{
|
||||
|
|
|
@ -19,7 +19,7 @@ public:
|
|||
// generic
|
||||
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||
void setKeyset(const sKeyset* keyset);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setCliOutputMode(CliOutputMode type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
// nca specfic
|
||||
|
@ -37,7 +37,7 @@ private:
|
|||
fnd::IFile* mFile;
|
||||
bool mOwnIFile;
|
||||
const sKeyset* mKeyset;
|
||||
CliOutputType mCliOutputType;
|
||||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
struct sExtract
|
||||
|
|
|
@ -4,7 +4,7 @@ NpdmProcess::NpdmProcess() :
|
|||
mFile(nullptr),
|
||||
mOwnIFile(false),
|
||||
mKeyset(nullptr),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||
mVerify(false)
|
||||
{
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ void NpdmProcess::process()
|
|||
validateAciFromAcid(mNpdm.getAci(), mNpdm.getAcid());
|
||||
}
|
||||
|
||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||
{
|
||||
// npdm binary
|
||||
displayNpdmHeader(mNpdm);
|
||||
|
@ -67,9 +67,9 @@ void NpdmProcess::setKeyset(const sKeyset* keyset)
|
|||
mKeyset = keyset;
|
||||
}
|
||||
|
||||
void NpdmProcess::setCliOutputMode(CliOutputType type)
|
||||
void NpdmProcess::setCliOutputMode(CliOutputMode type)
|
||||
{
|
||||
mCliOutputType = type;
|
||||
mCliOutputMode = type;
|
||||
}
|
||||
|
||||
void NpdmProcess::setVerifyMode(bool verify)
|
||||
|
@ -296,9 +296,7 @@ void NpdmProcess::validateAcidSignature(const nx::AcidBinary& acid)
|
|||
acid.verifyBinary(mKeyset->acid_sign_key);
|
||||
}
|
||||
catch (...) {
|
||||
// this is minimal even though it's a warning because it's a validation method
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACID Signature: FAIL\n");
|
||||
printf("[WARNING] ACID Signature: FAIL\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -308,20 +306,17 @@ void NpdmProcess::validateAciFromAcid(const nx::AciBinary& aci, const nx::AcidBi
|
|||
// check Program ID
|
||||
if (acid.getProgramIdMin() > 0 && aci.getProgramId() < acid.getProgramIdMin())
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI ProgramId: FAIL (Outside Legal Range)\n");
|
||||
printf("[WARNING] ACI ProgramId: FAIL (Outside Legal Range)\n");
|
||||
}
|
||||
else if (acid.getProgramIdMax() > 0 && aci.getProgramId() > acid.getProgramIdMax())
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI ProgramId: FAIL (Outside Legal Range)\n");
|
||||
printf("[WARNING] ACI ProgramId: FAIL (Outside Legal Range)\n");
|
||||
}
|
||||
|
||||
// Check FAC
|
||||
if (aci.getFac().getFormatVersion() != acid.getFac().getFormatVersion())
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/FAC FormatVersion: FAIL (%d != %d (expected))\n", aci.getFac().getFormatVersion(),acid.getFac().getFormatVersion());
|
||||
printf("[WARNING] ACI/FAC FormatVersion: FAIL (%d != %d (expected))\n", aci.getFac().getFormatVersion(),acid.getFac().getFormatVersion());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < aci.getFac().getFsaRightsList().getSize(); i++)
|
||||
|
@ -335,8 +330,8 @@ void NpdmProcess::validateAciFromAcid(const nx::AciBinary& aci, const nx::AcidBi
|
|||
|
||||
if (fsaRightFound == false)
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/FAC FsaRights: FAIL (%s not permitted)\n", kFsaFlag[aci.getFac().getFsaRightsList()[i]].c_str());
|
||||
|
||||
printf("[WARNING] ACI/FAC FsaRights: FAIL (%s not permitted)\n", kFsaFlag[aci.getFac().getFsaRightsList()[i]].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,8 +346,8 @@ void NpdmProcess::validateAciFromAcid(const nx::AciBinary& aci, const nx::AcidBi
|
|||
|
||||
if (rightFound == false)
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/FAC ContentOwnerId: FAIL (%08x not permitted)\n", aci.getFac().getContentOwnerIdList()[i]);
|
||||
|
||||
printf("[WARNING] ACI/FAC ContentOwnerId: FAIL (%08x not permitted)\n", aci.getFac().getContentOwnerIdList()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,8 +362,8 @@ void NpdmProcess::validateAciFromAcid(const nx::AciBinary& aci, const nx::AcidBi
|
|||
|
||||
if (rightFound == false)
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/FAC ContentOwnerId: FAIL (%08x not permitted)\n", aci.getFac().getSaveDataOwnerIdList()[i]);
|
||||
|
||||
printf("[WARNING] ACI/FAC ContentOwnerId: FAIL (%08x not permitted)\n", aci.getFac().getSaveDataOwnerIdList()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,8 +379,8 @@ void NpdmProcess::validateAciFromAcid(const nx::AciBinary& aci, const nx::AcidBi
|
|||
|
||||
if (rightFound == false)
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/SAC ServiceList: FAIL (%s%s not permitted)\n", aci.getSac().getServiceList()[i].getName().c_str(), aci.getSac().getServiceList()[i].isServer()? " (Server)" : "");
|
||||
|
||||
printf("[WARNING] ACI/SAC ServiceList: FAIL (%s%s not permitted)\n", aci.getSac().getServiceList()[i].getName().c_str(), aci.getSac().getServiceList()[i].isServer()? " (Server)" : "");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,23 +388,19 @@ void NpdmProcess::validateAciFromAcid(const nx::AciBinary& aci, const nx::AcidBi
|
|||
// check thread info
|
||||
if (aci.getKc().getThreadInfo().getMaxCpuId() != acid.getKc().getThreadInfo().getMaxCpuId())
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/KC ThreadInfo/MaxCpuId: FAIL (%d not permitted)\n", aci.getKc().getThreadInfo().getMaxCpuId());
|
||||
printf("[WARNING] ACI/KC ThreadInfo/MaxCpuId: FAIL (%d not permitted)\n", aci.getKc().getThreadInfo().getMaxCpuId());
|
||||
}
|
||||
if (aci.getKc().getThreadInfo().getMinCpuId() != acid.getKc().getThreadInfo().getMinCpuId())
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/KC ThreadInfo/MinCpuId: FAIL (%d not permitted)\n", aci.getKc().getThreadInfo().getMinCpuId());
|
||||
printf("[WARNING] ACI/KC ThreadInfo/MinCpuId: FAIL (%d not permitted)\n", aci.getKc().getThreadInfo().getMinCpuId());
|
||||
}
|
||||
if (aci.getKc().getThreadInfo().getMaxPriority() != acid.getKc().getThreadInfo().getMaxPriority())
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/KC ThreadInfo/MaxPriority: FAIL (%d not permitted)\n", aci.getKc().getThreadInfo().getMaxPriority());
|
||||
printf("[WARNING] ACI/KC ThreadInfo/MaxPriority: FAIL (%d not permitted)\n", aci.getKc().getThreadInfo().getMaxPriority());
|
||||
}
|
||||
if (aci.getKc().getThreadInfo().getMinPriority() != acid.getKc().getThreadInfo().getMinPriority())
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/KC ThreadInfo/MinPriority: FAIL (%d not permitted)\n", aci.getKc().getThreadInfo().getMinPriority());
|
||||
printf("[WARNING] ACI/KC ThreadInfo/MinPriority: FAIL (%d not permitted)\n", aci.getKc().getThreadInfo().getMinPriority());
|
||||
}
|
||||
// check system calls
|
||||
for (size_t i = 0; i < aci.getKc().getSystemCalls().getSystemCalls().getSize(); i++)
|
||||
|
@ -423,8 +414,8 @@ void NpdmProcess::validateAciFromAcid(const nx::AciBinary& aci, const nx::AcidBi
|
|||
|
||||
if (rightFound == false)
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/KC SystemCallList: FAIL (%s not permitted)\n", kSysCall[aci.getKc().getSystemCalls().getSystemCalls()[i]].c_str());
|
||||
|
||||
printf("[WARNING] ACI/KC SystemCallList: FAIL (%s not permitted)\n", kSysCall[aci.getKc().getSystemCalls().getSystemCalls()[i]].c_str());
|
||||
}
|
||||
}
|
||||
// check memory maps
|
||||
|
@ -440,8 +431,8 @@ void NpdmProcess::validateAciFromAcid(const nx::AciBinary& aci, const nx::AcidBi
|
|||
if (rightFound == false)
|
||||
{
|
||||
const nx::MemoryMappingHandler::sMemoryMapping& map = aci.getKc().getMemoryMaps().getMemoryMaps()[i];
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/KC MemoryMap: FAIL (0x%016" PRIx64 " - 0x%016" PRIx64 " (perm=%s) (type=%s) not permitted)\n", (uint64_t)map.addr << 12, ((uint64_t)(map.addr + map.size) << 12) - 1, kMemMapPerm[map.perm].c_str(), kMemMapType[map.type].c_str());
|
||||
|
||||
printf("[WARNING] ACI/KC MemoryMap: FAIL (0x%016" PRIx64 " - 0x%016" PRIx64 " (perm=%s) (type=%s) not permitted)\n", (uint64_t)map.addr << 12, ((uint64_t)(map.addr + map.size) << 12) - 1, kMemMapPerm[map.perm].c_str(), kMemMapType[map.type].c_str());
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < aci.getKc().getMemoryMaps().getIoMemoryMaps().getSize(); i++)
|
||||
|
@ -456,8 +447,8 @@ void NpdmProcess::validateAciFromAcid(const nx::AciBinary& aci, const nx::AcidBi
|
|||
if (rightFound == false)
|
||||
{
|
||||
const nx::MemoryMappingHandler::sMemoryMapping& map = aci.getKc().getMemoryMaps().getIoMemoryMaps()[i];
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/KC IoMemoryMap: FAIL (0x%016" PRIx64 " - 0x%016" PRIx64 " (perm=%s) (type=%s) not permitted)\n", (uint64_t)map.addr << 12, ((uint64_t)(map.addr + map.size) << 12) - 1, kMemMapPerm[map.perm].c_str(), kMemMapType[map.type].c_str());
|
||||
|
||||
printf("[WARNING] ACI/KC IoMemoryMap: FAIL (0x%016" PRIx64 " - 0x%016" PRIx64 " (perm=%s) (type=%s) not permitted)\n", (uint64_t)map.addr << 12, ((uint64_t)(map.addr + map.size) << 12) - 1, kMemMapPerm[map.perm].c_str(), kMemMapType[map.type].c_str());
|
||||
}
|
||||
}
|
||||
// check interupts
|
||||
|
@ -472,29 +463,25 @@ void NpdmProcess::validateAciFromAcid(const nx::AciBinary& aci, const nx::AcidBi
|
|||
|
||||
if (rightFound == false)
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/KC InteruptsList: FAIL (0x%0x not permitted)\n", aci.getKc().getInterupts().getInteruptList()[i]);
|
||||
printf("[WARNING] ACI/KC InteruptsList: FAIL (0x%0x not permitted)\n", aci.getKc().getInterupts().getInteruptList()[i]);
|
||||
}
|
||||
}
|
||||
// check misc params
|
||||
if (aci.getKc().getMiscParams().getProgramType() != acid.getKc().getMiscParams().getProgramType())
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/KC ProgramType: FAIL (%d not permitted)\n", aci.getKc().getMiscParams().getProgramType());
|
||||
printf("[WARNING] ACI/KC ProgramType: FAIL (%d not permitted)\n", aci.getKc().getMiscParams().getProgramType());
|
||||
}
|
||||
// check kernel version
|
||||
uint32_t aciKernelVersion = (uint32_t)aci.getKc().getKernelVersion().getVerMajor() << 16 | (uint32_t)aci.getKc().getKernelVersion().getVerMinor();
|
||||
uint32_t acidKernelVersion = (uint32_t)acid.getKc().getKernelVersion().getVerMajor() << 16 | (uint32_t)acid.getKc().getKernelVersion().getVerMinor();
|
||||
if (aciKernelVersion < acidKernelVersion)
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/KC RequiredKernelVersion: FAIL (%d.%d not permitted)\n", aci.getKc().getKernelVersion().getVerMajor(), aci.getKc().getKernelVersion().getVerMinor());
|
||||
printf("[WARNING] ACI/KC RequiredKernelVersion: FAIL (%d.%d not permitted)\n", aci.getKc().getKernelVersion().getVerMajor(), aci.getKc().getKernelVersion().getVerMinor());
|
||||
}
|
||||
// check handle table size
|
||||
if (aci.getKc().getHandleTableSize().getHandleTableSize() > acid.getKc().getHandleTableSize().getHandleTableSize())
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/KC HandleTableSize: FAIL (0x%x too large)\n", aci.getKc().getHandleTableSize().getHandleTableSize());
|
||||
printf("[WARNING] ACI/KC HandleTableSize: FAIL (0x%x too large)\n", aci.getKc().getHandleTableSize().getHandleTableSize());
|
||||
}
|
||||
// check misc flags
|
||||
for (size_t i = 0; i < aci.getKc().getMiscFlags().getFlagList().getSize(); i++)
|
||||
|
@ -508,8 +495,7 @@ void NpdmProcess::validateAciFromAcid(const nx::AciBinary& aci, const nx::AcidBi
|
|||
|
||||
if (rightFound == false)
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] ACI/KC MiscFlag: FAIL (%s not permitted)\n", kMiscFlag[aci.getKc().getMiscFlags().getFlagList()[i]].c_str());
|
||||
printf("[WARNING] ACI/KC MiscFlag: FAIL (%s not permitted)\n", kMiscFlag[aci.getKc().getMiscFlags().getFlagList()[i]].c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ public:
|
|||
|
||||
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||
void setKeyset(const sKeyset* keyset);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setCliOutputMode(CliOutputMode type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
const nx::NpdmBinary& getNpdmBinary() const;
|
||||
|
@ -27,7 +27,7 @@ private:
|
|||
fnd::IFile* mFile;
|
||||
bool mOwnIFile;
|
||||
const sKeyset* mKeyset;
|
||||
CliOutputType mCliOutputType;
|
||||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
nx::NpdmBinary mNpdm;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
NroProcess::NroProcess():
|
||||
mFile(nullptr),
|
||||
mOwnIFile(false),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||
mVerify(false),
|
||||
mInstructionType(nx::npdm::INSTR_64BIT),
|
||||
mListApi(false),
|
||||
|
@ -35,8 +35,11 @@ void NroProcess::process()
|
|||
importHeader();
|
||||
importCodeSegments();
|
||||
importApiList();
|
||||
displayHeader();
|
||||
displayRoMetaData();
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||
{
|
||||
displayHeader();
|
||||
displayRoMetaData();
|
||||
}
|
||||
if (mIsHomebrewNro)
|
||||
mAssetProc.process();
|
||||
}
|
||||
|
@ -47,9 +50,9 @@ void NroProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
|||
mOwnIFile = ownIFile;
|
||||
}
|
||||
|
||||
void NroProcess::setCliOutputMode(CliOutputType type)
|
||||
void NroProcess::setCliOutputMode(CliOutputMode type)
|
||||
{
|
||||
mCliOutputType = type;
|
||||
mCliOutputMode = type;
|
||||
}
|
||||
|
||||
void NroProcess::setVerifyMode(bool verify)
|
||||
|
@ -111,7 +114,7 @@ void NroProcess::importHeader()
|
|||
{
|
||||
mIsHomebrewNro = true;
|
||||
mAssetProc.setInputFile(new OffsetAdjustedIFile(mFile, false, mHdr.getNroSize(), mFile->size() - mHdr.getNroSize()), true);
|
||||
mAssetProc.setCliOutputMode(mCliOutputType);
|
||||
mAssetProc.setCliOutputMode(mCliOutputMode);
|
||||
mAssetProc.setVerifyMode(mVerify);
|
||||
}
|
||||
else
|
||||
|
@ -164,48 +167,45 @@ void NroProcess::importApiList()
|
|||
void NroProcess::displayHeader()
|
||||
{
|
||||
#define _HEXDUMP_L(var, len) do { for (size_t a__a__A = 0; a__a__A < len; a__a__A++) printf("%02x", var[a__a__A]); } while(0)
|
||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||
printf("[NRO Header]\n");
|
||||
printf(" RoCrt: ");
|
||||
_HEXDUMP_L(mHdr.getRoCrt().data, nx::nro::kRoCrtSize);
|
||||
printf("\n");
|
||||
printf(" ModuleId: ");
|
||||
_HEXDUMP_L(mHdr.getModuleId().data, nx::nro::kModuleIdSize);
|
||||
printf("\n");
|
||||
printf(" NroSize: 0x%" PRIx32 "\n", mHdr.getNroSize());
|
||||
printf(" Program Sections:\n");
|
||||
printf(" .text:\n");
|
||||
printf(" Offset: 0x%" PRIx32 "\n", mHdr.getTextInfo().memory_offset);
|
||||
printf(" Size: 0x%" PRIx32 "\n", mHdr.getTextInfo().size);
|
||||
printf(" .ro:\n");
|
||||
printf(" Offset: 0x%" PRIx32 "\n", mHdr.getRoInfo().memory_offset);
|
||||
printf(" Size: 0x%" PRIx32 "\n", mHdr.getRoInfo().size);
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf("[NRO Header]\n");
|
||||
printf(" RoCrt: ");
|
||||
_HEXDUMP_L(mHdr.getRoCrt().data, nx::nro::kRoCrtSize);
|
||||
printf("\n");
|
||||
printf(" ModuleId: ");
|
||||
_HEXDUMP_L(mHdr.getModuleId().data, nx::nro::kModuleIdSize);
|
||||
printf("\n");
|
||||
printf(" NroSize: 0x%" PRIx32 "\n", mHdr.getNroSize());
|
||||
printf(" Program Sections:\n");
|
||||
printf(" .text:\n");
|
||||
printf(" Offset: 0x%" PRIx32 "\n", mHdr.getTextInfo().memory_offset);
|
||||
printf(" Size: 0x%" PRIx32 "\n", mHdr.getTextInfo().size);
|
||||
printf(" .ro:\n");
|
||||
printf(" Offset: 0x%" PRIx32 "\n", mHdr.getRoInfo().memory_offset);
|
||||
printf(" Size: 0x%" PRIx32 "\n", mHdr.getRoInfo().size);
|
||||
if (mCliOutputType >= OUTPUT_VERBOSE)
|
||||
{
|
||||
printf(" .api_info:\n");
|
||||
printf(" Offset: 0x%" PRIx32 "\n", mHdr.getRoEmbeddedInfo().memory_offset);
|
||||
printf(" Size: 0x%" PRIx32 "\n", mHdr.getRoEmbeddedInfo().size);
|
||||
printf(" .dynstr:\n");
|
||||
printf(" Offset: 0x%" PRIx32 "\n", mHdr.getRoDynStrInfo().memory_offset);
|
||||
printf(" Size: 0x%" PRIx32 "\n", mHdr.getRoDynStrInfo().size);
|
||||
printf(" .dynsym:\n");
|
||||
printf(" Offset: 0x%" PRIx32 "\n", mHdr.getRoDynSymInfo().memory_offset);
|
||||
printf(" Size: 0x%" PRIx32 "\n", mHdr.getRoDynSymInfo().size);
|
||||
}
|
||||
printf(" .data:\n");
|
||||
printf(" Offset: 0x%" PRIx32 "\n", mHdr.getDataInfo().memory_offset);
|
||||
printf(" Size: 0x%" PRIx32 "\n", mHdr.getDataInfo().size);
|
||||
printf(" .bss:\n");
|
||||
printf(" Size: 0x%" PRIx32 "\n", mHdr.getBssSize());
|
||||
printf(" .api_info:\n");
|
||||
printf(" Offset: 0x%" PRIx32 "\n", mHdr.getRoEmbeddedInfo().memory_offset);
|
||||
printf(" Size: 0x%" PRIx32 "\n", mHdr.getRoEmbeddedInfo().size);
|
||||
printf(" .dynstr:\n");
|
||||
printf(" Offset: 0x%" PRIx32 "\n", mHdr.getRoDynStrInfo().memory_offset);
|
||||
printf(" Size: 0x%" PRIx32 "\n", mHdr.getRoDynStrInfo().size);
|
||||
printf(" .dynsym:\n");
|
||||
printf(" Offset: 0x%" PRIx32 "\n", mHdr.getRoDynSymInfo().memory_offset);
|
||||
printf(" Size: 0x%" PRIx32 "\n", mHdr.getRoDynSymInfo().size);
|
||||
}
|
||||
printf(" .data:\n");
|
||||
printf(" Offset: 0x%" PRIx32 "\n", mHdr.getDataInfo().memory_offset);
|
||||
printf(" Size: 0x%" PRIx32 "\n", mHdr.getDataInfo().size);
|
||||
printf(" .bss:\n");
|
||||
printf(" Size: 0x%" PRIx32 "\n", mHdr.getBssSize());
|
||||
|
||||
#undef _HEXDUMP_L
|
||||
}
|
||||
|
||||
void NroProcess::displayRoMetaData()
|
||||
{
|
||||
if (mApiList.size() > 0 && (mListApi || mCliOutputType > OUTPUT_NORMAL))
|
||||
if (mApiList.size() > 0 && (mListApi || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)))
|
||||
{
|
||||
printf("[SDK API List]\n");
|
||||
for (size_t i = 0; i < mApiList.size(); i++)
|
||||
|
@ -216,7 +216,7 @@ void NroProcess::displayRoMetaData()
|
|||
printf(" Module: %s\n", mApiList[i].getModuleName().c_str());
|
||||
}
|
||||
}
|
||||
if (mDynSymbolList.getDynamicSymbolList().getSize() > 0 && (mListSymbols || mCliOutputType > OUTPUT_NORMAL))
|
||||
if (mDynSymbolList.getDynamicSymbolList().getSize() > 0 && (mListSymbols || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)))
|
||||
{
|
||||
printf("[Symbol List]\n");
|
||||
for (size_t i = 0; i < mDynSymbolList.getDynamicSymbolList().getSize(); i++)
|
||||
|
@ -225,7 +225,6 @@ void NroProcess::displayRoMetaData()
|
|||
printf(" %s [SHN=%s (%04x)][STT=%s]\n", symbol.name.c_str(), getSectionIndexStr(symbol.shn_index), symbol.shn_index, getSymbolTypeStr(symbol.symbol_type));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const char* NroProcess::getApiTypeStr(SdkApiString::ApiType type) const
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
void process();
|
||||
|
||||
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setCliOutputMode(CliOutputMode type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
void setInstructionType(nx::npdm::InstructionType type);
|
||||
|
@ -38,7 +38,7 @@ private:
|
|||
fnd::IFile* mFile;
|
||||
bool mOwnIFile;
|
||||
|
||||
CliOutputType mCliOutputType;
|
||||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
nx::npdm::InstructionType mInstructionType;
|
||||
bool mListApi;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
NsoProcess::NsoProcess():
|
||||
mFile(nullptr),
|
||||
mOwnIFile(false),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||
mVerify(false),
|
||||
mInstructionType(nx::npdm::INSTR_64BIT),
|
||||
mListApi(false),
|
||||
|
@ -34,8 +34,11 @@ void NsoProcess::process()
|
|||
importHeader();
|
||||
importCodeSegments();
|
||||
importApiList();
|
||||
displayNsoHeader();
|
||||
displayRoMetaData();
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||
{
|
||||
displayNsoHeader();
|
||||
displayRoMetaData();
|
||||
}
|
||||
}
|
||||
|
||||
void NsoProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
||||
|
@ -44,9 +47,9 @@ void NsoProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
|||
mOwnIFile = ownIFile;
|
||||
}
|
||||
|
||||
void NsoProcess::setCliOutputMode(CliOutputType type)
|
||||
void NsoProcess::setCliOutputMode(CliOutputMode type)
|
||||
{
|
||||
mCliOutputType = type;
|
||||
mCliOutputMode = type;
|
||||
}
|
||||
|
||||
void NsoProcess::setVerifyMode(bool verify)
|
||||
|
@ -204,75 +207,73 @@ void NsoProcess::displayNsoHeader()
|
|||
{
|
||||
#define _HEXDUMP_L(var, len) do { for (size_t a__a__A = 0; a__a__A < len; a__a__A++) printf("%02x", var[a__a__A]); } while(0)
|
||||
|
||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||
printf("[NSO Header]\n");
|
||||
printf(" ModuleId: ");
|
||||
_HEXDUMP_L(mNsoHdr.getModuleId().data, nx::nso::kModuleIdSize);
|
||||
printf("\n");
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT))
|
||||
printf(" Program Segments:\n");
|
||||
printf(" .module_name:\n");
|
||||
printf(" FileOffset: 0x%" PRIx32 "\n", mNsoHdr.getModuleNameInfo().offset);
|
||||
printf(" FileSize: 0x%" PRIx32 "\n", mNsoHdr.getModuleNameInfo().size);
|
||||
printf(" .text:\n");
|
||||
printf(" FileOffset: 0x%" PRIx32 "\n", mNsoHdr.getTextSegmentInfo().file_layout.offset);
|
||||
printf(" FileSize: 0x%" PRIx32 "%s\n", mNsoHdr.getTextSegmentInfo().file_layout.size, mNsoHdr.getTextSegmentInfo().is_compressed? " (COMPRESSED)" : "");
|
||||
printf(" .ro:\n");
|
||||
printf(" FileOffset: 0x%" PRIx32 "\n", mNsoHdr.getRoSegmentInfo().file_layout.offset);
|
||||
printf(" FileSize: 0x%" PRIx32 "%s\n", mNsoHdr.getRoSegmentInfo().file_layout.size, mNsoHdr.getRoSegmentInfo().is_compressed? " (COMPRESSED)" : "");
|
||||
printf(" .data:\n");
|
||||
printf(" FileOffset: 0x%" PRIx32 "\n", mNsoHdr.getDataSegmentInfo().file_layout.offset);
|
||||
printf(" FileSize: 0x%" PRIx32 "%s\n", mNsoHdr.getDataSegmentInfo().file_layout.size, mNsoHdr.getDataSegmentInfo().is_compressed? " (COMPRESSED)" : "");
|
||||
printf(" Program Sections:\n");
|
||||
printf(" .text:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNsoHdr.getTextSegmentInfo().memory_layout.offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNsoHdr.getTextSegmentInfo().memory_layout.size);
|
||||
if (mNsoHdr.getTextSegmentInfo().is_hashed && _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf("[NSO Header]\n");
|
||||
printf(" ModuleId: ");
|
||||
_HEXDUMP_L(mNsoHdr.getModuleId().data, nx::nso::kModuleIdSize);
|
||||
printf(" Hash: ");
|
||||
_HEXDUMP_L(mNsoHdr.getTextSegmentInfo().hash.bytes, 32);
|
||||
printf("\n");
|
||||
printf(" Program Segments:\n");
|
||||
printf(" .module_name:\n");
|
||||
printf(" FileOffset: 0x%" PRIx32 "\n", mNsoHdr.getModuleNameInfo().offset);
|
||||
printf(" FileSize: 0x%" PRIx32 "\n", mNsoHdr.getModuleNameInfo().size);
|
||||
printf(" .text:\n");
|
||||
printf(" FileOffset: 0x%" PRIx32 "\n", mNsoHdr.getTextSegmentInfo().file_layout.offset);
|
||||
printf(" FileSize: 0x%" PRIx32 "%s\n", mNsoHdr.getTextSegmentInfo().file_layout.size, mNsoHdr.getTextSegmentInfo().is_compressed? " (COMPRESSED)" : "");
|
||||
printf(" .ro:\n");
|
||||
printf(" FileOffset: 0x%" PRIx32 "\n", mNsoHdr.getRoSegmentInfo().file_layout.offset);
|
||||
printf(" FileSize: 0x%" PRIx32 "%s\n", mNsoHdr.getRoSegmentInfo().file_layout.size, mNsoHdr.getRoSegmentInfo().is_compressed? " (COMPRESSED)" : "");
|
||||
printf(" .data:\n");
|
||||
printf(" FileOffset: 0x%" PRIx32 "\n", mNsoHdr.getDataSegmentInfo().file_layout.offset);
|
||||
printf(" FileSize: 0x%" PRIx32 "%s\n", mNsoHdr.getDataSegmentInfo().file_layout.size, mNsoHdr.getDataSegmentInfo().is_compressed? " (COMPRESSED)" : "");
|
||||
printf(" Program Sections:\n");
|
||||
printf(" .text:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNsoHdr.getTextSegmentInfo().memory_layout.offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNsoHdr.getTextSegmentInfo().memory_layout.size);
|
||||
if (mNsoHdr.getTextSegmentInfo().is_hashed && mCliOutputType >= OUTPUT_VERBOSE)
|
||||
{
|
||||
printf(" Hash: ");
|
||||
_HEXDUMP_L(mNsoHdr.getTextSegmentInfo().hash.bytes, 32);
|
||||
printf("\n");
|
||||
}
|
||||
printf(" .ro:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNsoHdr.getRoSegmentInfo().memory_layout.offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNsoHdr.getRoSegmentInfo().memory_layout.size);
|
||||
if (mNsoHdr.getRoSegmentInfo().is_hashed && mCliOutputType >= OUTPUT_VERBOSE)
|
||||
{
|
||||
printf(" Hash: ");
|
||||
_HEXDUMP_L(mNsoHdr.getRoSegmentInfo().hash.bytes, 32);
|
||||
printf("\n");
|
||||
}
|
||||
if (mCliOutputType >= OUTPUT_VERBOSE)
|
||||
{
|
||||
printf(" .api_info:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNsoHdr.getRoEmbeddedInfo().offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNsoHdr.getRoEmbeddedInfo().size);
|
||||
printf(" .dynstr:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNsoHdr.getRoDynStrInfo().offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNsoHdr.getRoDynStrInfo().size);
|
||||
printf(" .dynsym:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNsoHdr.getRoDynSymInfo().offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNsoHdr.getRoDynSymInfo().size);
|
||||
}
|
||||
|
||||
printf(" .data:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNsoHdr.getDataSegmentInfo().memory_layout.offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNsoHdr.getDataSegmentInfo().memory_layout.size);
|
||||
if (mNsoHdr.getDataSegmentInfo().is_hashed && mCliOutputType >= OUTPUT_VERBOSE)
|
||||
{
|
||||
printf(" Hash: ");
|
||||
_HEXDUMP_L(mNsoHdr.getDataSegmentInfo().hash.bytes, 32);
|
||||
printf("\n");
|
||||
}
|
||||
printf(" .bss:\n");
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNsoHdr.getBssSize());
|
||||
}
|
||||
printf(" .ro:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNsoHdr.getRoSegmentInfo().memory_layout.offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNsoHdr.getRoSegmentInfo().memory_layout.size);
|
||||
if (mNsoHdr.getRoSegmentInfo().is_hashed && _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" Hash: ");
|
||||
_HEXDUMP_L(mNsoHdr.getRoSegmentInfo().hash.bytes, 32);
|
||||
printf("\n");
|
||||
}
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" .api_info:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNsoHdr.getRoEmbeddedInfo().offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNsoHdr.getRoEmbeddedInfo().size);
|
||||
printf(" .dynstr:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNsoHdr.getRoDynStrInfo().offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNsoHdr.getRoDynStrInfo().size);
|
||||
printf(" .dynsym:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNsoHdr.getRoDynSymInfo().offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNsoHdr.getRoDynSymInfo().size);
|
||||
}
|
||||
|
||||
printf(" .data:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNsoHdr.getDataSegmentInfo().memory_layout.offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNsoHdr.getDataSegmentInfo().memory_layout.size);
|
||||
if (mNsoHdr.getDataSegmentInfo().is_hashed && _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" Hash: ");
|
||||
_HEXDUMP_L(mNsoHdr.getDataSegmentInfo().hash.bytes, 32);
|
||||
printf("\n");
|
||||
}
|
||||
printf(" .bss:\n");
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNsoHdr.getBssSize());
|
||||
#undef _HEXDUMP_L
|
||||
}
|
||||
|
||||
void NsoProcess::displayRoMetaData()
|
||||
{
|
||||
if (mApiList.size() > 0 && (mListApi || mCliOutputType > OUTPUT_NORMAL))
|
||||
if (mApiList.size() > 0 && (mListApi || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)))
|
||||
{
|
||||
printf("[SDK API List]\n");
|
||||
for (size_t i = 0; i < mApiList.size(); i++)
|
||||
|
@ -283,7 +284,7 @@ void NsoProcess::displayRoMetaData()
|
|||
printf(" Module: %s\n", mApiList[i].getModuleName().c_str());
|
||||
}
|
||||
}
|
||||
if (mDynSymbolList.getDynamicSymbolList().getSize() > 0 && (mListSymbols || mCliOutputType > OUTPUT_NORMAL))
|
||||
if (mDynSymbolList.getDynamicSymbolList().getSize() > 0 && (mListSymbols || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)))
|
||||
{
|
||||
printf("[Symbol List]\n");
|
||||
for (size_t i = 0; i < mDynSymbolList.getDynamicSymbolList().getSize(); i++)
|
||||
|
@ -292,9 +293,9 @@ void NsoProcess::displayRoMetaData()
|
|||
printf(" %s [SHN=%s (%04x)][STT=%s]\n", symbol.name.c_str(), getSectionIndexStr(symbol.shn_index), symbol.shn_index, getSymbolTypeStr(symbol.symbol_type));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const char* NsoProcess::getApiTypeStr(SdkApiString::ApiType type) const
|
||||
{
|
||||
const char* str;
|
||||
|
|
|
@ -19,7 +19,7 @@ public:
|
|||
void process();
|
||||
|
||||
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setCliOutputMode(CliOutputMode type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
void setInstructionType(nx::npdm::InstructionType type);
|
||||
|
@ -31,7 +31,7 @@ private:
|
|||
fnd::IFile* mFile;
|
||||
bool mOwnIFile;
|
||||
|
||||
CliOutputType mCliOutputType;
|
||||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
nx::npdm::InstructionType mInstructionType;
|
||||
bool mListApi;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
PfsProcess::PfsProcess() :
|
||||
mFile(nullptr),
|
||||
mOwnIFile(false),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||
mVerify(false),
|
||||
mExtractPath(),
|
||||
mExtract(false),
|
||||
|
@ -46,10 +46,12 @@ void PfsProcess::process()
|
|||
mFile->read(scratch.getBytes(), 0, scratch.getSize());
|
||||
mPfs.importBinary(scratch.getBytes(), scratch.getSize());
|
||||
|
||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||
{
|
||||
displayHeader();
|
||||
if (mListFs || mCliOutputType >= OUTPUT_VERBOSE)
|
||||
displayFs();
|
||||
if (mListFs || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
displayFs();
|
||||
}
|
||||
if (mPfs.getFsType() == mPfs.TYPE_HFS0 && mVerify)
|
||||
validateHfs();
|
||||
if (mExtract)
|
||||
|
@ -62,9 +64,9 @@ void PfsProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
|||
mOwnIFile = ownIFile;
|
||||
}
|
||||
|
||||
void PfsProcess::setCliOutputMode(CliOutputType type)
|
||||
void PfsProcess::setCliOutputMode(CliOutputMode type)
|
||||
{
|
||||
mCliOutputType = type;
|
||||
mCliOutputMode = type;
|
||||
}
|
||||
|
||||
void PfsProcess::setVerifyMode(bool verify)
|
||||
|
@ -107,7 +109,7 @@ void PfsProcess::displayFs()
|
|||
for (size_t i = 0; i < mPfs.getFileList().getSize(); i++)
|
||||
{
|
||||
printf(" %s", mPfs.getFileList()[i].name.c_str());
|
||||
if (mCliOutputType >= OUTPUT_VERBOSE)
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT))
|
||||
{
|
||||
if (mPfs.getFsType() == mPfs.TYPE_PFS0)
|
||||
printf(" (offset=0x%" PRIx64 ", size=0x%" PRIx64 ")\n", (uint64_t)mPfs.getFileList()[i].offset, (uint64_t)mPfs.getFileList()[i].size);
|
||||
|
@ -149,9 +151,7 @@ void PfsProcess::validateHfs()
|
|||
crypto::sha::Sha256(mCache.getBytes(), file[i].hash_protected_size, hash.bytes);
|
||||
if (hash != file[i].hash)
|
||||
{
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] HFS0 %s%s%s: FAIL (bad hash)\n", !mMountName.empty()? mMountName.c_str() : "", (!mMountName.empty() && mMountName.at(mMountName.length()-1) != '/' )? "/" : "", file[i].name.c_str());
|
||||
|
||||
printf("[WARNING] HFS0 %s%s%s: FAIL (bad hash)\n", !mMountName.empty()? mMountName.c_str() : "", (!mMountName.empty() && mMountName.at(mMountName.length()-1) != '/' )? "/" : "", file[i].name.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ void PfsProcess::extractFs()
|
|||
fnd::io::appendToPath(file_path, mExtractPath);
|
||||
fnd::io::appendToPath(file_path, file[i].name);
|
||||
|
||||
if (mCliOutputType >= OUTPUT_VERBOSE)
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||
printf("extract=[%s]\n", file_path.c_str());
|
||||
|
||||
outFile.open(file_path, outFile.Create);
|
||||
|
|
|
@ -16,7 +16,7 @@ public:
|
|||
|
||||
// generic
|
||||
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setCliOutputMode(CliOutputMode type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
// pfs specific
|
||||
|
@ -32,7 +32,7 @@ private:
|
|||
|
||||
fnd::IFile* mFile;
|
||||
bool mOwnIFile;
|
||||
CliOutputType mCliOutputType;
|
||||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
std::string mExtractPath;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
RomfsProcess::RomfsProcess() :
|
||||
mFile(nullptr),
|
||||
mOwnIFile(false),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||
mVerify(false),
|
||||
mExtractPath(),
|
||||
mExtract(false),
|
||||
|
@ -37,10 +37,12 @@ void RomfsProcess::process()
|
|||
|
||||
resolveRomfs();
|
||||
|
||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||
{
|
||||
displayHeader();
|
||||
if (mListFs || mCliOutputType >= OUTPUT_VERBOSE)
|
||||
displayFs();
|
||||
if (mListFs || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
displayFs();
|
||||
}
|
||||
if (mExtract)
|
||||
extractFs();
|
||||
}
|
||||
|
@ -51,9 +53,9 @@ void RomfsProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
|||
mOwnIFile = ownIFile;
|
||||
}
|
||||
|
||||
void RomfsProcess::setCliOutputMode(CliOutputType type)
|
||||
void RomfsProcess::setCliOutputMode(CliOutputMode type)
|
||||
{
|
||||
mCliOutputType = type;
|
||||
mCliOutputMode = type;
|
||||
}
|
||||
|
||||
void RomfsProcess::setVerifyMode(bool verify)
|
||||
|
@ -94,7 +96,7 @@ void RomfsProcess::displayFile(const sFile& file, size_t tab) const
|
|||
{
|
||||
printTab(tab);
|
||||
printf("%s", file.name.c_str());
|
||||
if (mCliOutputType >= OUTPUT_VERBOSE)
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT))
|
||||
{
|
||||
printf(" (offset=0x%" PRIx64 ", size=0x%" PRIx64 ")", file.offset, file.size);
|
||||
}
|
||||
|
@ -154,9 +156,8 @@ void RomfsProcess::extractDir(const std::string& path, const sDirectory& dir)
|
|||
fnd::io::appendToPath(file_path, dir_path);
|
||||
fnd::io::appendToPath(file_path, dir.file_list[i].name);
|
||||
|
||||
if (mCliOutputType >= OUTPUT_VERBOSE)
|
||||
printf("extract=[%s]\n", file_path.c_str());
|
||||
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||
printf("extract=[%s]\n", file_path.c_str());
|
||||
|
||||
outFile.open(file_path, outFile.Create);
|
||||
mFile->seek(dir.file_list[i].offset);
|
||||
|
|
|
@ -95,7 +95,7 @@ public:
|
|||
|
||||
// generic
|
||||
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setCliOutputMode(CliOutputMode type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
// romfs specific
|
||||
|
@ -110,7 +110,7 @@ private:
|
|||
|
||||
fnd::IFile* mFile;
|
||||
bool mOwnIFile;
|
||||
CliOutputType mCliOutputType;
|
||||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
std::string mExtractPath;
|
||||
|
|
|
@ -45,8 +45,10 @@ void UserSettings::showHelp()
|
|||
printf(" -k, --keyset Specify keyset file\n");
|
||||
printf(" -t, --type Specify input file type [xci, pfs, romfs, nca, npdm, cnmt, nso, nro, nacp, aset]\n");
|
||||
printf(" -y, --verify Verify file\n");
|
||||
printf("\n Output Options:\n");
|
||||
printf(" --showkeys Show keys generated\n");
|
||||
printf(" --showlayout Show layout metadata\n");
|
||||
printf(" -v, --verbose Verbose output\n");
|
||||
printf(" -q, --quiet Minimal output\n");
|
||||
printf("\n XCI (GameCard Image)\n");
|
||||
printf(" nstool [--listfs] [--update <dir> --logo <dir> --normal <dir> --secure <dir>] <.xci file>\n");
|
||||
printf(" --listfs Print file system in embedded partitions\n");
|
||||
|
@ -101,9 +103,9 @@ bool UserSettings::isVerifyFile() const
|
|||
return mVerifyFile;
|
||||
}
|
||||
|
||||
CliOutputType UserSettings::getCliOutputType() const
|
||||
CliOutputMode UserSettings::getCliOutputMode() const
|
||||
{
|
||||
return mOutputType;
|
||||
return mOutputMode;
|
||||
}
|
||||
|
||||
bool UserSettings::isListFs() const
|
||||
|
@ -223,18 +225,24 @@ void UserSettings::populateCmdArgs(int argc, char** argv, sCmdArgs& cmd_args)
|
|||
cmd_args.verify_file = true;
|
||||
}
|
||||
|
||||
else if (args[i] == "--showkeys")
|
||||
{
|
||||
if (hasParamter) throw fnd::Exception(kModuleName, args[i] + " does not take a parameter.");
|
||||
cmd_args.show_keys = true;
|
||||
}
|
||||
|
||||
else if (args[i] == "--showlayout")
|
||||
{
|
||||
if (hasParamter) throw fnd::Exception(kModuleName, args[i] + " does not take a parameter.");
|
||||
cmd_args.show_layout = true;
|
||||
}
|
||||
|
||||
else if (args[i] == "-v" || args[i] == "--verbose")
|
||||
{
|
||||
if (hasParamter) throw fnd::Exception(kModuleName, args[i] + " does not take a parameter.");
|
||||
cmd_args.verbose_output = true;
|
||||
}
|
||||
|
||||
else if (args[i] == "-q" || args[i] == "--quiet")
|
||||
{
|
||||
if (hasParamter) throw fnd::Exception(kModuleName, args[i] + " does not take a parameter.");
|
||||
cmd_args.minimal_output = true;
|
||||
}
|
||||
|
||||
else if (args[i] == "-k" || args[i] == "--keyset")
|
||||
{
|
||||
if (!hasParamter) throw fnd::Exception(kModuleName, args[i] + " requries a parameter.");
|
||||
|
@ -588,8 +596,6 @@ void UserSettings::populateUserSettings(sCmdArgs& args)
|
|||
// check invalid input
|
||||
if (args.input_path.isSet == false)
|
||||
throw fnd::Exception(kModuleName, "No input file specified");
|
||||
if (args.verbose_output.isSet && args.minimal_output.isSet)
|
||||
throw fnd::Exception(kModuleName, "Options --verbose and --quiet cannot be used together.");
|
||||
|
||||
// save arguments
|
||||
mInputPath = *args.input_path;
|
||||
|
@ -618,13 +624,22 @@ void UserSettings::populateUserSettings(sCmdArgs& args)
|
|||
mAssetIconPath = args.asset_icon_path;
|
||||
mAssetNacpPath = args.asset_nacp_path;
|
||||
|
||||
// determine output path
|
||||
// determine output mode
|
||||
mOutputMode = _BIT(OUTPUT_BASIC);
|
||||
if (args.verbose_output.isSet)
|
||||
mOutputType = OUTPUT_VERBOSE;
|
||||
else if (args.minimal_output.isSet)
|
||||
mOutputType = OUTPUT_MINIMAL;
|
||||
else
|
||||
mOutputType = OUTPUT_NORMAL;
|
||||
{
|
||||
mOutputMode |= _BIT(OUTPUT_KEY_DATA);
|
||||
mOutputMode |= _BIT(OUTPUT_LAYOUT);
|
||||
mOutputMode |= _BIT(OUTPUT_EXTENDED);
|
||||
}
|
||||
if (args.show_keys.isSet)
|
||||
{
|
||||
mOutputMode |= _BIT(OUTPUT_KEY_DATA);
|
||||
}
|
||||
if (args.show_layout.isSet)
|
||||
{
|
||||
mOutputMode |= _BIT(OUTPUT_LAYOUT);
|
||||
}
|
||||
|
||||
// determine input file type
|
||||
if (args.file_type.isSet)
|
||||
|
|
|
@ -18,7 +18,7 @@ public:
|
|||
const sKeyset& getKeyset() const;
|
||||
FileType getFileType() const;
|
||||
bool isVerifyFile() const;
|
||||
CliOutputType getCliOutputType() const;
|
||||
CliOutputMode getCliOutputMode() const;
|
||||
|
||||
// specialised toggles
|
||||
bool isListFs() const;
|
||||
|
@ -50,8 +50,9 @@ private:
|
|||
sOptional<std::string> keyset_path;
|
||||
sOptional<std::string> file_type;
|
||||
sOptional<bool> verify_file;
|
||||
sOptional<bool> show_keys;
|
||||
sOptional<bool> show_layout;
|
||||
sOptional<bool> verbose_output;
|
||||
sOptional<bool> minimal_output;
|
||||
sOptional<bool> list_fs;
|
||||
sOptional<std::string> update_path;
|
||||
sOptional<std::string> logo_path;
|
||||
|
@ -75,7 +76,7 @@ private:
|
|||
FileType mFileType;
|
||||
sKeyset mKeyset;
|
||||
bool mVerifyFile;
|
||||
CliOutputType mOutputType;
|
||||
CliOutputMode mOutputMode;
|
||||
|
||||
bool mListFs;
|
||||
sOptional<std::string> mXciUpdatePath;
|
||||
|
|
|
@ -7,7 +7,7 @@ XciProcess::XciProcess() :
|
|||
mFile(nullptr),
|
||||
mOwnIFile(false),
|
||||
mKeyset(nullptr),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||
mVerify(false),
|
||||
mListFs(false),
|
||||
mRootPfs(),
|
||||
|
@ -49,10 +49,8 @@ void XciProcess::process()
|
|||
mHdr.importBinary(scratch.getBytes(), scratch.getSize());
|
||||
|
||||
// display header
|
||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||
{
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||
displayHeader();
|
||||
}
|
||||
|
||||
// process root partition
|
||||
processRootPfs();
|
||||
|
@ -72,9 +70,9 @@ void XciProcess::setKeyset(const sKeyset* keyset)
|
|||
mKeyset = keyset;
|
||||
}
|
||||
|
||||
void XciProcess::setCliOutputMode(CliOutputType type)
|
||||
void XciProcess::setCliOutputMode(CliOutputMode type)
|
||||
{
|
||||
mCliOutputType = type;
|
||||
mCliOutputMode = type;
|
||||
}
|
||||
|
||||
void XciProcess::setVerifyMode(bool verify)
|
||||
|
@ -142,63 +140,81 @@ inline const char* getCardClockRate(uint32_t acc_ctrl_1)
|
|||
|
||||
void XciProcess::displayHeader()
|
||||
{
|
||||
printf("[XCI HEADER]\n");
|
||||
printf(" Magic: HEAD\n");
|
||||
printf(" RomAreaStartPage: 0x%0x", mHdr.getRomAreaStartPage());
|
||||
if (mHdr.getRomAreaStartPage() != (uint32_t)(-1))
|
||||
printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getRomAreaStartPage()));
|
||||
printf("\n");
|
||||
printf(" BackupAreaStartPage: 0x%0x", mHdr.getBackupAreaStartPage());
|
||||
if (mHdr.getBackupAreaStartPage() != (uint32_t)(-1))
|
||||
printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getBackupAreaStartPage()));
|
||||
printf("\n");
|
||||
printf(" KekIndex: %d\n", mHdr.getKekIndex());
|
||||
printf(" TitleKeyDecIndex: %d\n", mHdr.getTitleKeyDecIndex());
|
||||
printf(" RomSize: 0x%x (%s)\n", mHdr.getRomSizeType(), getRomSizeStr(mHdr.getRomSizeType()));
|
||||
printf(" CardHeaderVersion: %d\n", mHdr.getCardHeaderVersion());
|
||||
printf(" Flags: 0x%x\n", mHdr.getFlags());
|
||||
printf(" AutoBoot: %s\n", getBoolStr(_HAS_BIT(mHdr.getFlags(), nx::xci::FLAG_AUTOBOOT)));
|
||||
printf(" HistoryErase: %s\n", getBoolStr(_HAS_BIT(mHdr.getFlags(), nx::xci::FLAG_HISTORY_ERASE)));
|
||||
printf(" RepairTool: %s\n", getBoolStr(_HAS_BIT(mHdr.getFlags(), nx::xci::FLAG_REPAIR_TOOL)));
|
||||
printf(" PackageId: 0x%" PRIx64 "\n", mHdr.getPackageId());
|
||||
printf(" ValidDataEndPage: 0x%x", mHdr.getValidDataEndPage());
|
||||
if (mHdr.getValidDataEndPage() != (uint32_t)(-1))
|
||||
printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getValidDataEndPage()));
|
||||
printf("\n");
|
||||
printf(" AesIv: ");
|
||||
fnd::SimpleTextOutput::hexDump(mHdr.getAesCbcIv().iv, sizeof(mHdr.getAesCbcIv().iv));
|
||||
printf(" PartitionFs:\n");
|
||||
printf(" Offset: 0x%" PRIx64 "\n", mHdr.getPartitionFsAddress());
|
||||
printf(" Size: 0x%" PRIx64 "\n", mHdr.getPartitionFsSize());
|
||||
printf(" Hash: ");
|
||||
fnd::SimpleTextOutput::hexDump(mHdr.getPartitionFsHash().bytes, sizeof(mHdr.getPartitionFsHash().bytes));
|
||||
printf(" InitialData:\n");
|
||||
printf(" Hash: ");
|
||||
fnd::SimpleTextOutput::hexDump(mHdr.getInitialDataHash().bytes, sizeof(mHdr.getInitialDataHash().bytes));
|
||||
printf(" SelSec: 0x%x\n", mHdr.getSelSec());
|
||||
printf(" SelT1Key: 0x%x\n", mHdr.getSelT1Key());
|
||||
printf(" SelKey: 0x%x\n", mHdr.getSelKey());
|
||||
printf(" LimArea: 0x%x", mHdr.getLimAreaPage());
|
||||
if (mHdr.getLimAreaPage() != (uint32_t)(-1))
|
||||
printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getLimAreaPage()));
|
||||
printf("\n");
|
||||
printf("[XCI Header]\n");
|
||||
printf(" Magic: HEAD\n");
|
||||
printf(" KekIndex: %d\n", mHdr.getKekIndex());
|
||||
printf(" TitleKeyDecIndex: %d\n", mHdr.getTitleKeyDecIndex());
|
||||
printf(" RomSize: 0x%x (%s)\n", mHdr.getRomSizeType(), getRomSizeStr(mHdr.getRomSizeType()));
|
||||
printf(" CardHeaderVersion: %d\n", mHdr.getCardHeaderVersion());
|
||||
printf(" Flags: 0x%x\n", mHdr.getFlags());
|
||||
printf(" AutoBoot: %s\n", getBoolStr(_HAS_BIT(mHdr.getFlags(), nx::xci::FLAG_AUTOBOOT)));
|
||||
printf(" HistoryErase: %s\n", getBoolStr(_HAS_BIT(mHdr.getFlags(), nx::xci::FLAG_HISTORY_ERASE)));
|
||||
printf(" RepairTool: %s\n", getBoolStr(_HAS_BIT(mHdr.getFlags(), nx::xci::FLAG_REPAIR_TOOL)));
|
||||
printf(" PackageId: 0x%" PRIx64 "\n", mHdr.getPackageId());
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" InitialDataHash: \n");
|
||||
fnd::SimpleTextOutput::hexDump(mHdr.getInitialDataHash().bytes, sizeof(mHdr.getInitialDataHash().bytes));
|
||||
}
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" Enc Header AES-IV: ");
|
||||
fnd::SimpleTextOutput::hexDump(mHdr.getAesCbcIv().iv, sizeof(mHdr.getAesCbcIv().iv));
|
||||
}
|
||||
printf(" SelSec: 0x%x\n", mHdr.getSelSec());
|
||||
printf(" SelT1Key: 0x%x\n", mHdr.getSelT1Key());
|
||||
printf(" SelKey: 0x%x\n", mHdr.getSelKey());
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT))
|
||||
{
|
||||
printf(" RomAreaStartPage: 0x%0x", mHdr.getRomAreaStartPage());
|
||||
if (mHdr.getRomAreaStartPage() != (uint32_t)(-1))
|
||||
printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getRomAreaStartPage()));
|
||||
printf("\n");
|
||||
|
||||
printf(" BackupAreaStartPage: 0x%0x", mHdr.getBackupAreaStartPage());
|
||||
if (mHdr.getBackupAreaStartPage() != (uint32_t)(-1))
|
||||
printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getBackupAreaStartPage()));
|
||||
printf("\n");
|
||||
|
||||
printf(" FwVersion: v%d.%d\n", mHdr.getFwVerMajor(), mHdr.getFwVerMinor());
|
||||
printf(" AccCtrl1: 0x%x\n", mHdr.getAccCtrl1());
|
||||
printf(" CardClockRate: %s\n", getCardClockRate(mHdr.getAccCtrl1()));
|
||||
printf(" Wait1TimeRead: 0x%x\n", mHdr.getWait1TimeRead());
|
||||
printf(" Wait2TimeRead: 0x%x\n", mHdr.getWait2TimeRead());
|
||||
printf(" Wait1TimeWrite: 0x%x\n", mHdr.getWait1TimeWrite());
|
||||
printf(" Wait2TimeWrite: 0x%x\n", mHdr.getWait2TimeWrite());
|
||||
printf(" FwMode: 0x%x\n", mHdr.getFwMode());
|
||||
printf(" ValidDataEndPage: 0x%x", mHdr.getValidDataEndPage());
|
||||
if (mHdr.getValidDataEndPage() != (uint32_t)(-1))
|
||||
printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getValidDataEndPage()));
|
||||
printf("\n");
|
||||
|
||||
printf(" LimArea: 0x%x", mHdr.getLimAreaPage());
|
||||
if (mHdr.getLimAreaPage() != (uint32_t)(-1))
|
||||
printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getLimAreaPage()));
|
||||
printf("\n");
|
||||
|
||||
printf(" PartitionFs Header:\n");
|
||||
printf(" Offset: 0x%" PRIx64 "\n", mHdr.getPartitionFsAddress());
|
||||
printf(" Size: 0x%" PRIx64 "\n", mHdr.getPartitionFsSize());
|
||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||
{
|
||||
printf(" Hash: ");
|
||||
fnd::SimpleTextOutput::hexDump(mHdr.getPartitionFsHash().bytes, sizeof(mHdr.getPartitionFsHash().bytes));
|
||||
}
|
||||
}
|
||||
|
||||
printf("[XCI Extended Header]\n");
|
||||
printf(" FwVersion: v%d.%d\n", mHdr.getFwVerMajor(), mHdr.getFwVerMinor());
|
||||
printf(" AccCtrl1: 0x%x\n", mHdr.getAccCtrl1());
|
||||
printf(" CardClockRate: %s\n", getCardClockRate(mHdr.getAccCtrl1()));
|
||||
printf(" Wait1TimeRead: 0x%x\n", mHdr.getWait1TimeRead());
|
||||
printf(" Wait2TimeRead: 0x%x\n", mHdr.getWait2TimeRead());
|
||||
printf(" Wait1TimeWrite: 0x%x\n", mHdr.getWait1TimeWrite());
|
||||
printf(" Wait2TimeWrite: 0x%x\n", mHdr.getWait2TimeWrite());
|
||||
printf(" FwMode: 0x%x\n", mHdr.getFwMode());
|
||||
printf(" Update Partition Info:\n");
|
||||
#define _SPLIT_VER(ver) ( (ver>>26) & 0x3f), ( (ver>>20) & 0x3f), ( (ver>>16) & 0xf), (ver & 0xffff)
|
||||
printf(" UppVersion: v%" PRId32 " (%d.%d.%d.%d)\n", mHdr.getUppVersion(), _SPLIT_VER(mHdr.getUppVersion()));
|
||||
printf(" CUP Version: v%" PRId32 " (%d.%d.%d.%d)\n", mHdr.getUppVersion(), _SPLIT_VER(mHdr.getUppVersion()));
|
||||
#undef _SPLIT_VER
|
||||
printf(" UppHash: ");
|
||||
printf(" CUP TitleId: %016" PRIx64 "\n", mHdr.getUppId());
|
||||
printf(" Partition Hash: ");
|
||||
fnd::SimpleTextOutput::hexDump(mHdr.getUppHash(), 8);
|
||||
printf(" UppId: %016" PRIx64 "\n", mHdr.getUppId());
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool XciProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash)
|
||||
|
@ -217,9 +233,7 @@ void XciProcess::validateXciSignature()
|
|||
crypto::sha::Sha256((byte_t*)&mHdrPage.header, sizeof(nx::sXciHeader), calc_hash.bytes);
|
||||
if (crypto::rsa::pkcs::rsaVerify(mKeyset->xci.header_sign_key, crypto::sha::HASH_SHA256, calc_hash.bytes, mHdrPage.signature) != 0)
|
||||
{
|
||||
// this is minimal even though it's a warning because it's a validation method
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
printf("[WARNING] XCI Header Signature: FAIL \n");
|
||||
printf("[WARNING] XCI Header Signature: FAIL \n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,7 +246,7 @@ void XciProcess::processRootPfs()
|
|||
mRootPfs.setInputFile(new OffsetAdjustedIFile(mFile, SHARED_IFILE, mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize()), OWN_IFILE);
|
||||
mRootPfs.setListFs(mListFs);
|
||||
mRootPfs.setVerifyMode(false);
|
||||
mRootPfs.setCliOutputMode(mCliOutputType);
|
||||
mRootPfs.setCliOutputMode(mCliOutputMode);
|
||||
mRootPfs.setMountPointName(kXciMountPointName);
|
||||
mRootPfs.process();
|
||||
}
|
||||
|
@ -252,7 +266,7 @@ void XciProcess::processPartitionPfs()
|
|||
tmp.setInputFile(new OffsetAdjustedIFile(mFile, SHARED_IFILE, mHdr.getPartitionFsAddress() + rootPartitions[i].offset, rootPartitions[i].size), OWN_IFILE);
|
||||
tmp.setListFs(mListFs);
|
||||
tmp.setVerifyMode(mVerify);
|
||||
tmp.setCliOutputMode(mCliOutputType);
|
||||
tmp.setCliOutputMode(mCliOutputMode);
|
||||
tmp.setMountPointName(kXciMountPointName + rootPartitions[i].name);
|
||||
for (size_t j = 0; j < mExtractInfo.size(); j++)
|
||||
{
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
// generic
|
||||
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||
void setKeyset(const sKeyset* keyset);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setCliOutputMode(CliOutputMode type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
// xci specific
|
||||
|
@ -34,7 +34,7 @@ private:
|
|||
fnd::IFile* mFile;
|
||||
bool mOwnIFile;
|
||||
const sKeyset* mKeyset;
|
||||
CliOutputType mCliOutputType;
|
||||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
struct sExtractInfo
|
||||
|
|
|
@ -25,7 +25,7 @@ int main(int argc, char** argv)
|
|||
xci.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||
|
||||
xci.setKeyset(&user_set.getKeyset());
|
||||
xci.setCliOutputMode(user_set.getCliOutputType());
|
||||
xci.setCliOutputMode(user_set.getCliOutputMode());
|
||||
xci.setVerifyMode(user_set.isVerifyFile());
|
||||
|
||||
if (user_set.getXciUpdatePath().isSet)
|
||||
|
@ -45,7 +45,7 @@ int main(int argc, char** argv)
|
|||
PfsProcess pfs;
|
||||
|
||||
pfs.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||
pfs.setCliOutputMode(user_set.getCliOutputType());
|
||||
pfs.setCliOutputMode(user_set.getCliOutputMode());
|
||||
pfs.setVerifyMode(user_set.isVerifyFile());
|
||||
|
||||
if (user_set.getFsPath().isSet)
|
||||
|
@ -59,7 +59,7 @@ int main(int argc, char** argv)
|
|||
RomfsProcess romfs;
|
||||
|
||||
romfs.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||
romfs.setCliOutputMode(user_set.getCliOutputType());
|
||||
romfs.setCliOutputMode(user_set.getCliOutputMode());
|
||||
romfs.setVerifyMode(user_set.isVerifyFile());
|
||||
|
||||
if (user_set.getFsPath().isSet)
|
||||
|
@ -74,7 +74,7 @@ int main(int argc, char** argv)
|
|||
|
||||
nca.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||
nca.setKeyset(&user_set.getKeyset());
|
||||
nca.setCliOutputMode(user_set.getCliOutputType());
|
||||
nca.setCliOutputMode(user_set.getCliOutputMode());
|
||||
nca.setVerifyMode(user_set.isVerifyFile());
|
||||
|
||||
|
||||
|
@ -96,7 +96,7 @@ int main(int argc, char** argv)
|
|||
|
||||
npdm.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||
npdm.setKeyset(&user_set.getKeyset());
|
||||
npdm.setCliOutputMode(user_set.getCliOutputType());
|
||||
npdm.setCliOutputMode(user_set.getCliOutputMode());
|
||||
npdm.setVerifyMode(user_set.isVerifyFile());
|
||||
|
||||
npdm.process();
|
||||
|
@ -106,7 +106,7 @@ int main(int argc, char** argv)
|
|||
CnmtProcess cnmt;
|
||||
|
||||
cnmt.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||
cnmt.setCliOutputMode(user_set.getCliOutputType());
|
||||
cnmt.setCliOutputMode(user_set.getCliOutputMode());
|
||||
cnmt.setVerifyMode(user_set.isVerifyFile());
|
||||
|
||||
cnmt.process();
|
||||
|
@ -116,7 +116,7 @@ int main(int argc, char** argv)
|
|||
NsoProcess obj;
|
||||
|
||||
obj.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||
obj.setCliOutputMode(user_set.getCliOutputType());
|
||||
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||
obj.setVerifyMode(user_set.isVerifyFile());
|
||||
|
||||
obj.setInstructionType(user_set.getInstType());
|
||||
|
@ -130,7 +130,7 @@ int main(int argc, char** argv)
|
|||
NroProcess obj;
|
||||
|
||||
obj.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||
obj.setCliOutputMode(user_set.getCliOutputType());
|
||||
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||
obj.setVerifyMode(user_set.isVerifyFile());
|
||||
|
||||
obj.setInstructionType(user_set.getInstType());
|
||||
|
@ -153,7 +153,7 @@ int main(int argc, char** argv)
|
|||
NacpProcess nacp;
|
||||
|
||||
nacp.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||
nacp.setCliOutputMode(user_set.getCliOutputType());
|
||||
nacp.setCliOutputMode(user_set.getCliOutputMode());
|
||||
nacp.setVerifyMode(user_set.isVerifyFile());
|
||||
|
||||
nacp.process();
|
||||
|
@ -163,7 +163,7 @@ int main(int argc, char** argv)
|
|||
AssetProcess obj;
|
||||
|
||||
obj.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||
obj.setCliOutputMode(user_set.getCliOutputType());
|
||||
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||
obj.setVerifyMode(user_set.isVerifyFile());
|
||||
|
||||
if (user_set.getAssetIconPath().isSet)
|
||||
|
|
|
@ -31,13 +31,16 @@ enum FileType
|
|||
FILE_INVALID = -1,
|
||||
};
|
||||
|
||||
enum CliOutputType
|
||||
enum CliOutputModeFlag
|
||||
{
|
||||
OUTPUT_MINIMAL,
|
||||
OUTPUT_NORMAL,
|
||||
OUTPUT_VERBOSE
|
||||
OUTPUT_BASIC,
|
||||
OUTPUT_LAYOUT,
|
||||
OUTPUT_KEY_DATA,
|
||||
OUTPUT_EXTENDED
|
||||
};
|
||||
|
||||
typedef byte_t CliOutputMode;
|
||||
|
||||
template <typename T>
|
||||
struct sOptional
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue