diff --git a/lib/libnx/include/nx/FileSystemAccessControlBinary.h b/lib/libnx/include/nx/FileSystemAccessControlBinary.h index 3a822bc..90d6663 100644 --- a/lib/libnx/include/nx/FileSystemAccessControlBinary.h +++ b/lib/libnx/include/nx/FileSystemAccessControlBinary.h @@ -11,6 +11,29 @@ namespace nx class FileSystemAccessControlBinary : public fnd::ISerialisable { public: + struct sSaveDataOwnerId + { + nx::fac::SaveDataOwnerIdAccessType access_type; + uint64_t id; + + void operator=(const sSaveDataOwnerId& other) + { + access_type = other.access_type; + id = other.id; + } + + bool operator==(const sSaveDataOwnerId& other) const + { + return (access_type == other.access_type) \ + && (id == other.id); + } + + bool operator!=(const sSaveDataOwnerId& other) const + { + return !(*this == other); + } + }; + FileSystemAccessControlBinary(); FileSystemAccessControlBinary(const FileSystemAccessControlBinary& other); @@ -32,11 +55,11 @@ namespace nx const fnd::List& getFsaRightsList() const; void setFsaRightsList(const fnd::List& list); - const fnd::List& getContentOwnerIdList() const; - void setContentOwnerIdList(const fnd::List& list); + const fnd::List& getContentOwnerIdList() const; + void setContentOwnerIdList(const fnd::List& list); - const fnd::List& getSaveDataOwnerIdList() const; - void setSaveDataOwnerIdList(const fnd::List& list); + const fnd::List& getSaveDataOwnerIdList() const; + void setSaveDataOwnerIdList(const fnd::List& list); private: const std::string kModuleName = "FILE_SYSTEM_ACCESS_CONTROL_BINARY"; @@ -46,7 +69,7 @@ namespace nx // variables uint32_t mVersion; fnd::List mFsaRights; - fnd::List mContentOwnerIdList; - fnd::List mSaveDataOwnerIdList; + fnd::List mContentOwnerIdList; + fnd::List mSaveDataOwnerIdList; }; } \ No newline at end of file diff --git a/lib/libnx/include/nx/fac.h b/lib/libnx/include/nx/fac.h index 886c930..7707353 100644 --- a/lib/libnx/include/nx/fac.h +++ b/lib/libnx/include/nx/fac.h @@ -33,6 +33,13 @@ namespace nx FSA_DEBUG = 62, FSA_FULL_PERMISSION = 63, }; + + enum SaveDataOwnerIdAccessType + { + SDO_READ = 1, + SDO_WRITE, + SDO_READWRITE + }; } #pragma pack(push,1) @@ -42,8 +49,8 @@ namespace nx le_uint64_t fac_flags; struct sFacSection { - le_uint32_t start; - le_uint32_t end; + le_uint32_t offset; + le_uint32_t size; } content_owner_ids, save_data_owner_ids; // the data for these follow later in binary. start/end relative to base of FacData instance }; #pragma pack(pop) diff --git a/lib/libnx/source/AccessControlInfoBinary.cpp b/lib/libnx/source/AccessControlInfoBinary.cpp index 0abad1a..6c31f74 100644 --- a/lib/libnx/source/AccessControlInfoBinary.cpp +++ b/lib/libnx/source/AccessControlInfoBinary.cpp @@ -48,11 +48,11 @@ void nx::AccessControlInfoBinary::toBytes() uint32_t offset, size; } fac, sac, kc; - fac.offset = align(sizeof(sAciHeader), aci::kSectionAlignSize); + fac.offset = (uint32_t)align(sizeof(sAciHeader), aci::kSectionAlignSize); fac.size = (uint32_t)mFileSystemAccessControl.getBytes().size(); - sac.offset = align(fac.offset + fac.size, aci::kSectionAlignSize); + sac.offset = (uint32_t)align(fac.offset + fac.size, aci::kSectionAlignSize); sac.size = (uint32_t)mServiceAccessControl.getBytes().size(); - kc.offset = align(sac.offset + sac.size, aci::kSectionAlignSize); + kc.offset = (uint32_t)align(sac.offset + sac.size, aci::kSectionAlignSize); kc.size = (uint32_t)mKernelCapabilities.getBytes().size(); // get total size diff --git a/lib/libnx/source/AccessControlInfoDescBinary.cpp b/lib/libnx/source/AccessControlInfoDescBinary.cpp index 122d89c..a351f0b 100644 --- a/lib/libnx/source/AccessControlInfoDescBinary.cpp +++ b/lib/libnx/source/AccessControlInfoDescBinary.cpp @@ -52,11 +52,11 @@ void nx::AccessControlInfoDescBinary::toBytes() uint32_t offset, size; } fac, sac, kc; - fac.offset = align(sizeof(sAciDescHeader), aci::kSectionAlignSize); + fac.offset = (uint32_t)align(sizeof(sAciDescHeader), aci::kSectionAlignSize); fac.size = (uint32_t)mFileSystemAccessControl.getBytes().size(); - sac.offset = align(fac.offset + fac.size, aci::kSectionAlignSize); + sac.offset = (uint32_t)align(fac.offset + fac.size, aci::kSectionAlignSize); sac.size = (uint32_t)mServiceAccessControl.getBytes().size(); - kc.offset = align(sac.offset + sac.size, aci::kSectionAlignSize); + kc.offset = (uint32_t)align(sac.offset + sac.size, aci::kSectionAlignSize); kc.size = (uint32_t)mKernelCapabilities.getBytes().size(); // get total size @@ -72,7 +72,7 @@ void nx::AccessControlInfoDescBinary::toBytes() hdr->st_magic = aci::kAciDescStructMagic; // set "acid size" - hdr->signed_size = total_size - crypto::rsa::kRsa2048Size; + hdr->signed_size = (uint32_t)(total_size - crypto::rsa::kRsa2048Size); // set flags uint32_t flags = 0; diff --git a/lib/libnx/source/FileSystemAccessControlBinary.cpp b/lib/libnx/source/FileSystemAccessControlBinary.cpp index 60b1971..c2c4c94 100644 --- a/lib/libnx/source/FileSystemAccessControlBinary.cpp +++ b/lib/libnx/source/FileSystemAccessControlBinary.cpp @@ -41,10 +41,10 @@ void nx::FileSystemAccessControlBinary::toBytes() uint32_t offset, size; } content, savedata; - content.offset = align(sizeof(sFacHeader), fac::kSectionAlignSize); - content.size = (uint32_t)(mContentOwnerIdList.size() * sizeof(uint32_t)); - savedata.offset = content.offset + align(content.size, fac::kSectionAlignSize); - savedata.size = (uint32_t)(mSaveDataOwnerIdList.size() * sizeof(uint32_t)); + content.offset = (uint32_t)align(sizeof(sFacHeader), fac::kSectionAlignSize); + content.size = (uint32_t)(sizeof(uint32_t) + mContentOwnerIdList.size() * sizeof(uint64_t)); + savedata.offset = (uint32_t)(content.offset + (content.size > 0 ? align(content.size, fac::kSectionAlignSize) : 0)); + savedata.size = (uint32_t)(sizeof(uint32_t) + align(mSaveDataOwnerIdList.size(), fac::kSectionAlignSize) + mSaveDataOwnerIdList.size() * sizeof(uint64_t)); // get total size size_t total_size = _MAX(_MAX(content.offset + content.size, savedata.offset + savedata.size), align(sizeof(sFacHeader), fac::kSectionAlignSize)); @@ -64,24 +64,30 @@ void nx::FileSystemAccessControlBinary::toBytes() hdr->fac_flags = flag; // set offset/size - hdr->content_owner_ids.start = content.offset; + hdr->content_owner_ids.offset = content.offset; if (content.size > 0) - hdr->content_owner_ids.end = content.offset + content.size; - hdr->save_data_owner_ids.start = savedata.offset; + hdr->content_owner_ids.size = content.size; + hdr->save_data_owner_ids.offset = savedata.offset; if (savedata.size > 0) - hdr->save_data_owner_ids.end = savedata.offset + savedata.size; + hdr->save_data_owner_ids.size = savedata.size; // set ids - le_uint32_t* content_owner_ids = (le_uint32_t*)(mRawBinary.data() + content.offset); + le_uint32_t* content_owner_id_num = (le_uint32_t*)(mRawBinary.data() + content.offset); + le_uint64_t* content_owner_ids = (le_uint64_t*)(mRawBinary.data() + content.offset + sizeof(uint32_t)); + content_owner_id_num->set((uint32_t)mContentOwnerIdList.size()); for (size_t i = 0; i < mContentOwnerIdList.size(); i++) { content_owner_ids[i] = mContentOwnerIdList[i]; } - le_uint32_t* save_data_owner_ids = (le_uint32_t*)(mRawBinary.data() + savedata.offset); + le_uint32_t* save_data_owner_id_num = (le_uint32_t*)(mRawBinary.data() + savedata.offset); + byte_t* save_data_owner_id_accessibility_array = (mRawBinary.data() + savedata.offset + sizeof(uint32_t)); + le_uint64_t* save_data_owner_ids = (le_uint64_t*)(mRawBinary.data() + savedata.offset + sizeof(uint32_t) + align(mSaveDataOwnerIdList.size(), sizeof(uint32_t))); + save_data_owner_id_num->set((uint32_t)mSaveDataOwnerIdList.size()); for (size_t i = 0; i < mSaveDataOwnerIdList.size(); i++) { - save_data_owner_ids[i] = mSaveDataOwnerIdList[i]; + save_data_owner_id_accessibility_array[i] = mSaveDataOwnerIdList[i].access_type; + save_data_owner_ids[i] = mSaveDataOwnerIdList[i].id; } } @@ -107,7 +113,7 @@ void nx::FileSystemAccessControlBinary::fromBytes(const byte_t* data, size_t len } // get total size - size_t total_size = _MAX(_MAX(hdr.content_owner_ids.end.get(), hdr.save_data_owner_ids.end.get()), align(sizeof(sFacHeader), fac::kSectionAlignSize)); + size_t total_size = _MAX(_MAX(hdr.content_owner_ids.offset.get() + hdr.content_owner_ids.size.get(), hdr.save_data_owner_ids.offset.get() + hdr.save_data_owner_ids.size.get()), align(sizeof(sFacHeader), fac::kSectionAlignSize)); // validate binary size if (len < total_size) @@ -130,22 +136,23 @@ void nx::FileSystemAccessControlBinary::fromBytes(const byte_t* data, size_t len } // save ids - if (hdr.content_owner_ids.end.get() > hdr.content_owner_ids.start.get()) + if (hdr.content_owner_ids.size.get() > 0) { - le_uint32_t* content_owner_ids = (le_uint32_t*)(mRawBinary.data() + hdr.content_owner_ids.start.get()); - size_t content_owner_id_num = (hdr.content_owner_ids.end.get() - hdr.content_owner_ids.start.get()) / sizeof(uint32_t); + size_t content_owner_id_num = ((le_uint32_t*)(mRawBinary.data() + hdr.content_owner_ids.offset.get()))->get(); + le_uint64_t* content_owner_ids = (le_uint64_t*)(mRawBinary.data() + hdr.content_owner_ids.offset.get() + sizeof(uint32_t)); for (size_t i = 0; i < content_owner_id_num; i++) { mContentOwnerIdList.addElement(content_owner_ids[i].get()); } } - if (hdr.save_data_owner_ids.end.get() > hdr.save_data_owner_ids.start.get()) + if (hdr.save_data_owner_ids.size.get() > 0) { - le_uint32_t* save_data_owner_ids = (le_uint32_t*)(mRawBinary.data() + hdr.save_data_owner_ids.start.get()); - size_t save_data_owner_id_num = (hdr.save_data_owner_ids.end.get() - hdr.save_data_owner_ids.start.get()) / sizeof(uint32_t); + size_t save_data_owner_id_num = ((le_uint32_t*)(mRawBinary.data() + hdr.save_data_owner_ids.offset.get()))->get(); + byte_t* save_data_owner_id_accessibility_array = (mRawBinary.data() + hdr.save_data_owner_ids.offset.get() + sizeof(uint32_t)); + le_uint64_t* save_data_owner_ids = (le_uint64_t*)(mRawBinary.data() + hdr.save_data_owner_ids.offset.get() + sizeof(uint32_t) + align(save_data_owner_id_num, fac::kSectionAlignSize)); for (size_t i = 0; i < save_data_owner_id_num; i++) { - mSaveDataOwnerIdList.addElement(save_data_owner_ids[i].get()); + mSaveDataOwnerIdList.addElement({ (fac::SaveDataOwnerIdAccessType)save_data_owner_id_accessibility_array[i], save_data_owner_ids[i].get() }); } } } @@ -184,22 +191,22 @@ void nx::FileSystemAccessControlBinary::setFsaRightsList(const fnd::List& nx::FileSystemAccessControlBinary::getContentOwnerIdList() const +const fnd::List& nx::FileSystemAccessControlBinary::getContentOwnerIdList() const { return mContentOwnerIdList; } -void nx::FileSystemAccessControlBinary::setContentOwnerIdList(const fnd::List& list) +void nx::FileSystemAccessControlBinary::setContentOwnerIdList(const fnd::List& list) { mContentOwnerIdList = list; } -const fnd::List& nx::FileSystemAccessControlBinary::getSaveDataOwnerIdList() const +const fnd::List& nx::FileSystemAccessControlBinary::getSaveDataOwnerIdList() const { return mSaveDataOwnerIdList; } -void nx::FileSystemAccessControlBinary::setSaveDataOwnerIdList(const fnd::List& list) +void nx::FileSystemAccessControlBinary::setSaveDataOwnerIdList(const fnd::List& list) { mSaveDataOwnerIdList = list; } \ No newline at end of file diff --git a/lib/libnx/source/NpdmBinary.cpp b/lib/libnx/source/NpdmBinary.cpp index 3a77972..0d88e53 100644 --- a/lib/libnx/source/NpdmBinary.cpp +++ b/lib/libnx/source/NpdmBinary.cpp @@ -61,9 +61,9 @@ void nx::NpdmBinary::toBytes() uint32_t offset, size; } acid, aci; - acid.offset = align(sizeof(sNpdmHeader), npdm::kSectionAlignSize); + acid.offset = (uint32_t)align(sizeof(sNpdmHeader), npdm::kSectionAlignSize); acid.size = (uint32_t)mAcid.getBytes().size(); - aci.offset = acid.offset + align(acid.size, npdm::kSectionAlignSize); + aci.offset = (uint32_t)(acid.offset + align(acid.size, npdm::kSectionAlignSize)); aci.size = (uint32_t)mAci.getBytes().size(); diff --git a/programs/nstool/source/NpdmProcess.cpp b/programs/nstool/source/NpdmProcess.cpp index c87cc65..4c51bed 100644 --- a/programs/nstool/source/NpdmProcess.cpp +++ b/programs/nstool/source/NpdmProcess.cpp @@ -190,6 +190,15 @@ const std::string kFsaFlag[64] = "Debug", "FullPermission" }; + +const std::string kSaveDataOwnerAccessMode[4] = +{ + "IllegalAccessCondition", + "Read", + "Write", + "ReadWrite" +}; + const std::string kSysCall[0x80] = { "svc00", @@ -378,7 +387,7 @@ void NpdmProcess::validateAciFromAcid(const nx::AccessControlInfoBinary& aci, co if (rightFound == false) { - printf("[WARNING] ACI/FAC ContentOwnerId: FAIL (%08x not permitted)\n", aci.getFileSystemAccessControl().getContentOwnerIdList()[i]); + printf("[WARNING] ACI/FAC ContentOwnerId: FAIL (%016" PRIx64 " not permitted)\n", aci.getFileSystemAccessControl().getContentOwnerIdList()[i]); } } @@ -394,7 +403,7 @@ void NpdmProcess::validateAciFromAcid(const nx::AccessControlInfoBinary& aci, co if (rightFound == false) { - printf("[WARNING] ACI/FAC ContentOwnerId: FAIL (%08x not permitted)\n", aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i]); + printf("[WARNING] ACI/FAC ContentOwnerId: FAIL (%016" PRIx64 "(%d) not permitted)\n", aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].id, aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].access_type); } } @@ -590,25 +599,22 @@ void NpdmProcess::displayFac(const nx::FileSystemAccessControlBinary& fac) printf("%s", fac.getFsaRightsList()[i] != fac.getFsaRightsList().atBack() ? ", " : "\n"); } } - else - { - printf(" FS Rights: NONE\n"); - } if (fac.getContentOwnerIdList().size()) { printf(" Content Owner IDs:\n"); for (size_t i = 0; i < fac.getContentOwnerIdList().size(); i++) { - printf(" 0x%08x\n", fac.getContentOwnerIdList()[i]); + printf(" 0x%016" PRIx64 "\n", fac.getContentOwnerIdList()[i]); } } + if (fac.getSaveDataOwnerIdList().size()) { printf(" Save Data Owner IDs:\n"); for (size_t i = 0; i < fac.getSaveDataOwnerIdList().size(); i++) { - printf(" 0x%08x\n", fac.getSaveDataOwnerIdList()[i]); + printf(" 0x%016" PRIx64 " (%s)\n", fac.getSaveDataOwnerIdList()[i].id, kSaveDataOwnerAccessMode[fac.getSaveDataOwnerIdList()[i].access_type].c_str()); } } diff --git a/programs/nstool/source/NroProcess.cpp b/programs/nstool/source/NroProcess.cpp index f7aace2..1ecb652 100644 --- a/programs/nstool/source/NroProcess.cpp +++ b/programs/nstool/source/NroProcess.cpp @@ -91,6 +91,11 @@ void NroProcess::setAssetRomfsExtractPath(const std::string& path) mAssetProc.setRomfsExtractPath(path); } +const RoMetadataProcess& NroProcess::getRoMetadataProcess() const +{ + return mRoMeta; +} + void NroProcess::importHeader() { fnd::Vec scratch; diff --git a/programs/nstool/source/NroProcess.h b/programs/nstool/source/NroProcess.h index 3c5ee99..6fbdf59 100644 --- a/programs/nstool/source/NroProcess.h +++ b/programs/nstool/source/NroProcess.h @@ -31,6 +31,8 @@ public: void setAssetIconExtractPath(const std::string& path); void setAssetNacpExtractPath(const std::string& path); void setAssetRomfsExtractPath(const std::string& path); + + const RoMetadataProcess& getRoMetadataProcess() const; private: const std::string kModuleName = "NroProcess"; diff --git a/programs/nstool/source/NsoProcess.cpp b/programs/nstool/source/NsoProcess.cpp index ac68f3a..ff81e7f 100644 --- a/programs/nstool/source/NsoProcess.cpp +++ b/programs/nstool/source/NsoProcess.cpp @@ -66,6 +66,11 @@ void NsoProcess::setListSymbols(bool listSymbols) mRoMeta.setListSymbols(listSymbols); } +const RoMetadataProcess& NsoProcess::getRoMetadataProcess() const +{ + return mRoMeta; +} + void NsoProcess::importHeader() { fnd::Vec scratch; diff --git a/programs/nstool/source/NsoProcess.h b/programs/nstool/source/NsoProcess.h index 3fcecec..9088da2 100644 --- a/programs/nstool/source/NsoProcess.h +++ b/programs/nstool/source/NsoProcess.h @@ -24,6 +24,8 @@ public: void setInstructionType(nx::npdm::InstructionType type); void setListApi(bool listApi); void setListSymbols(bool listSymbols); + + const RoMetadataProcess& getRoMetadataProcess() const; private: const std::string kModuleName = "NsoProcess"; diff --git a/programs/nstool/source/RoMetadataProcess.cpp b/programs/nstool/source/RoMetadataProcess.cpp index 89b891a..af06e44 100644 --- a/programs/nstool/source/RoMetadataProcess.cpp +++ b/programs/nstool/source/RoMetadataProcess.cpp @@ -74,6 +74,31 @@ void RoMetadataProcess::setListSymbols(bool listSymbols) mListSymbols = listSymbols; } +const std::vector& RoMetadataProcess::getSdkVerApiList() const +{ + return mSdkVerApiList; +} + +const std::vector& RoMetadataProcess::getPublicApiList() const +{ + return mPublicApiList; +} + +const std::vector& RoMetadataProcess::getDebugApiList() const +{ + return mDebugApiList; +} + +const std::vector& RoMetadataProcess::getPrivateApiList() const +{ + return mPrivateApiList; +} + +const fnd::List& RoMetadataProcess::getSymbolList() const +{ + return mSymbolList.getSymbolList(); +} + void RoMetadataProcess::importApiList() { if (mApiInfo.size > 0) diff --git a/programs/nstool/source/RoMetadataProcess.h b/programs/nstool/source/RoMetadataProcess.h index 5ac36c7..477374f 100644 --- a/programs/nstool/source/RoMetadataProcess.h +++ b/programs/nstool/source/RoMetadataProcess.h @@ -27,6 +27,12 @@ public: void setInstructionType(nx::npdm::InstructionType type); void setListApi(bool listApi); void setListSymbols(bool listSymbols); + + const std::vector& getSdkVerApiList() const; + const std::vector& getPublicApiList() const; + const std::vector& getDebugApiList() const; + const std::vector& getPrivateApiList() const; + const fnd::List& getSymbolList() const; private: const std::string kModuleName = "RoMetadataProcess"; diff --git a/programs/nstool/source/XciProcess.cpp b/programs/nstool/source/XciProcess.cpp index cdf604b..5def29e 100644 --- a/programs/nstool/source/XciProcess.cpp +++ b/programs/nstool/source/XciProcess.cpp @@ -90,76 +90,38 @@ void XciProcess::setListFs(bool list_fs) mListFs = list_fs; } -inline const char* getBoolStr(bool isTrue) -{ - return isTrue? "TRUE" : "FALSE"; -} - -inline const char* getRomSizeStr(byte_t rom_size) -{ - const char* str = "unknown"; - switch (rom_size) - { - case (nx::xci::ROM_SIZE_1GB) : - str = "1GB"; - break; - case (nx::xci::ROM_SIZE_2GB) : - str = "2GB"; - break; - case (nx::xci::ROM_SIZE_4GB) : - str = "4GB"; - break; - case (nx::xci::ROM_SIZE_8GB) : - str = "8GB"; - break; - case (nx::xci::ROM_SIZE_16GB) : - str = "16GB"; - break; - case (nx::xci::ROM_SIZE_32GB) : - str = "32GB"; - break; - } - return str; -} - -inline const char* getCardClockRate(uint32_t acc_ctrl_1) -{ - const char* str = "unknown"; - switch (acc_ctrl_1) - { - case (nx::xci::CLOCK_RATE_25) : - str = "20 MHz"; - break; - case (nx::xci::CLOCK_RATE_50) : - str = "50 MHz"; - break; - - } - return str; -} - void XciProcess::displayHeader() { 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()); + printf(" RomSize: %s", getRomSizeStr(mHdr.getRomSizeType())); if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + printf(" (0x%x)", mHdr.getRomSizeType()); + printf("\n"); + printf(" PackageId: 0x%" PRIx64 "\n", mHdr.getPackageId()); + printf(" Flags: 0x%x\n", mHdr.getFlags()); + if (mHdr.getFlags() != 0) { - printf(" InitialDataHash: \n"); - fnd::SimpleTextOutput::hexDump(mHdr.getInitialDataHash().bytes, sizeof(mHdr.getInitialDataHash().bytes)); + for (uint32_t i = 0; i < 8; i++) + { + if (_HAS_BIT(mHdr.getFlags(), i)) + { + printf(" %s\n", getHeaderFlagStr(i)); + } + } } if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) { - printf(" Enc Header AES-IV: "); - fnd::SimpleTextOutput::hexDump(mHdr.getAesCbcIv().iv, sizeof(mHdr.getAesCbcIv().iv)); + printf(" InitialData:\n"); + printf(" KekIndex: %d\n", mHdr.getKekIndex()); + printf(" TitleKeyDecIndex: %d\n", mHdr.getTitleKeyDecIndex()); + printf(" Hash:\n"); + fnd::SimpleTextOutput::hexDump(mHdr.getInitialDataHash().bytes, sizeof(mHdr.getInitialDataHash().bytes), 0x10, 6); + } + if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + printf(" Enc Header AES-IV:\n"); + fnd::SimpleTextOutput::hexDump(mHdr.getAesCbcIv().iv, sizeof(mHdr.getAesCbcIv().iv), 0x10, 4); } printf(" SelSec: 0x%x\n", mHdr.getSelSec()); printf(" SelT1Key: 0x%x\n", mHdr.getSelT1Key()); @@ -187,34 +149,35 @@ void XciProcess::displayHeader() printf("\n"); printf(" PartitionFs Header:\n"); - printf(" Offset: 0x%" PRIx64 "\n", mHdr.getPartitionFsAddress()); - printf(" Size: 0x%" PRIx64 "\n", mHdr.getPartitionFsSize()); + 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(" Hash:\n"); + fnd::SimpleTextOutput::hexDump(mHdr.getPartitionFsHash().bytes, sizeof(mHdr.getPartitionFsHash().bytes), 0x10, 6); } } - 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"); + + if (mHdr.getFwVerMinor() != 0) + { + 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(" CUP Version: 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(" CUP TitleId: %016" PRIx64 "\n", mHdr.getUppId()); - printf(" Partition Hash: "); - fnd::SimpleTextOutput::hexDump(mHdr.getUppHash(), 8); - - - + printf(" CUP TitleId: %016" PRIx64 "\n", mHdr.getUppId()); + printf(" Partition Hash: "); + fnd::SimpleTextOutput::hexDump(mHdr.getUppHash(), 8); + } } bool XciProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash) @@ -273,4 +236,66 @@ void XciProcess::processPartitionPfs() tmp.process(); } -} \ No newline at end of file +} + +const char* XciProcess::getRomSizeStr(byte_t rom_size) const +{ + const char* str = "unknown"; + switch (rom_size) + { + case (nx::xci::ROM_SIZE_1GB): + str = "1GB"; + break; + case (nx::xci::ROM_SIZE_2GB): + str = "2GB"; + break; + case (nx::xci::ROM_SIZE_4GB): + str = "4GB"; + break; + case (nx::xci::ROM_SIZE_8GB): + str = "8GB"; + break; + case (nx::xci::ROM_SIZE_16GB): + str = "16GB"; + break; + case (nx::xci::ROM_SIZE_32GB): + str = "32GB"; + break; + } + return str; +} + +const char* XciProcess::getHeaderFlagStr(byte_t flag) const +{ + const char* str = "unknown"; + switch (flag) + { + case (nx::xci::FLAG_AUTOBOOT): + str = "AutoBoot"; + break; + case (nx::xci::FLAG_HISTORY_ERASE): + str = "HistoryErase"; + break; + case (nx::xci::FLAG_REPAIR_TOOL): + str = "RepairTool"; + break; + } + return str; +} + + +const char* XciProcess::getCardClockRate(uint32_t acc_ctrl_1) const +{ + const char* str = "unknown"; + switch (acc_ctrl_1) + { + case (nx::xci::CLOCK_RATE_25): + str = "20 MHz"; + break; + case (nx::xci::CLOCK_RATE_50): + str = "50 MHz"; + break; + + } + return str; +} diff --git a/programs/nstool/source/XciProcess.h b/programs/nstool/source/XciProcess.h index 224c308..68d8f54 100644 --- a/programs/nstool/source/XciProcess.h +++ b/programs/nstool/source/XciProcess.h @@ -67,4 +67,9 @@ private: void validateXciSignature(); void processRootPfs(); void processPartitionPfs(); + + // strings + const char* getRomSizeStr(byte_t rom_size) const; + const char* getHeaderFlagStr(byte_t flag) const; + const char* getCardClockRate(uint32_t acc_ctrl_1) const; }; \ No newline at end of file