From 20b4984ae317a6b2f67a731804fe537d11909a60 Mon Sep 17 00:00:00 2001 From: jakcron Date: Sat, 15 Jul 2017 18:28:01 +1000 Subject: [PATCH] [nx] Removed importBinary(const u8* bytes) from ISerialisableBinary and all children. AciHeader supports ACID version 1. Size bug in SacEntry fixed(?). Bitlength typo in SystemCallEntry fixed(?). MiscFlagsHandler now returns a fnd::List of flags, not the raw word. Forloop in MemoryMappingHandler fixed. --- lib/nx/AciHeader.cpp | 136 +++++++++++++++++++++++++++----- lib/nx/AciHeader.h | 68 +++++++++++----- lib/nx/FacBinary.cpp | 10 +-- lib/nx/FacBinary.h | 2 +- lib/nx/FacHeader.cpp | 71 +++++++++-------- lib/nx/FacHeader.h | 6 +- lib/nx/ISerialiseableBinary.h | 3 +- lib/nx/InteruptHandler.cpp | 7 +- lib/nx/InteruptHandler.h | 4 +- lib/nx/KcBinary.cpp | 10 +-- lib/nx/KcBinary.h | 2 +- lib/nx/MemoryMappingHandler.cpp | 7 +- lib/nx/MiscFlagsHandler.cpp | 55 ++++++++++--- lib/nx/MiscFlagsHandler.h | 38 ++++----- lib/nx/NcaHeader.cpp | 27 ++++--- lib/nx/NcaHeader.h | 4 +- lib/nx/NpdmHeader.cpp | 21 ++--- lib/nx/NpdmHeader.h | 4 +- lib/nx/SacBinary.cpp | 10 +-- lib/nx/SacBinary.h | 2 +- lib/nx/SacEntry.cpp | 20 +++-- lib/nx/SacEntry.h | 2 +- lib/nx/SystemCallEntry.h | 2 +- lib/nx/SystemCallHandler.cpp | 7 +- lib/nx/SystemCallHandler.h | 2 +- programs/ncatool/main.cpp | 2 +- 26 files changed, 357 insertions(+), 165 deletions(-) diff --git a/lib/nx/AciHeader.cpp b/lib/nx/AciHeader.cpp index ede72b3..bc52c6c 100644 --- a/lib/nx/AciHeader.cpp +++ b/lib/nx/AciHeader.cpp @@ -24,6 +24,7 @@ void AciHeader::calculateSectionOffsets() bool AciHeader::isEqual(const AciHeader & other) const { return (mType == other.mType) \ + && (mAcidSize == other.mAcidSize) \ && (mProgramId == other.mProgramId) \ && (mFac == other.mFac) \ && (mSac == other.mSac) \ @@ -39,6 +40,7 @@ void AciHeader::copyFrom(const AciHeader & other) else { mType = other.mType; + mAcidSize = other.mAcidSize; mProgramId = other.mProgramId; mFac = other.mFac; mSac = other.mSac; @@ -56,9 +58,9 @@ AciHeader::AciHeader(const AciHeader & other) importBinary(other.getBytes(), other.getSize()); } -AciHeader::AciHeader(const u8 * bytes) +AciHeader::AciHeader(const u8 * bytes, size_t len) { - importBinary(bytes); + importBinary(bytes, len); } bool AciHeader::operator==(const AciHeader & other) const @@ -104,8 +106,31 @@ void AciHeader::exportBinary() throw fnd::Exception(kModuleName, "Unexpected ACI type"); } - // set program - hdr->set_program_id(mProgramId); + if (mType == TYPE_ACI0) + { + // set program + hdr->set_program_id(mProgramId); + } + else if (mType == TYPE_ACID) + { + hdr->set_version(mAcidVersion); + switch (mAcidVersion) + { + case(0): + hdr->set_size(mAcidSize); + hdr->set_program_id_min(0); + hdr->set_program_id_max(0); + break; + case(1): + hdr->set_size(0); + hdr->set_program_id_min(mProgramIdMin); + hdr->set_program_id_max(mProgramIdMax); + break; + default: + throw fnd::Exception(kModuleName, "Unsupported ACID version"); + } + } + // set offset/size calculateSectionOffsets(); @@ -117,8 +142,13 @@ void AciHeader::exportBinary() hdr->kc().set_size(mKc.size); } -void AciHeader::importBinary(const u8 * bytes) +void AciHeader::importBinary(const u8 * bytes, size_t len) { + if (len < sizeof(sAciHeader)) + { + throw fnd::Exception(kModuleName, "ACI header too small"); + } + clearVariables(); mBinaryBlob.alloc(sizeof(sAciHeader)); @@ -139,7 +169,36 @@ void AciHeader::importBinary(const u8 * bytes) throw fnd::Exception(kModuleName, "ACI header corrupt"); } - mProgramId = hdr->program_id(); + + if (mType == TYPE_ACI0) + { + mProgramId = hdr->program_id(); + mAcidVersion = 0; + mAcidSize = 0; + mProgramIdMin = 0; + mProgramIdMax = 0; + } + else if (mType == TYPE_ACID) + { + mProgramId = 0; + mAcidVersion = hdr->version(); + switch (mAcidVersion) + { + case(0): + mAcidSize = hdr->size(); + mProgramIdMin = 0; + mProgramIdMax = 0; + break; + case(1): + mAcidSize = 0; + mProgramIdMin = hdr->program_id_min(); + mProgramIdMax = hdr->program_id_max(); + break; + default: + throw fnd::Exception(kModuleName, "Unsupported ACID version"); + } + } + mFac.offset = hdr->fac().offset(); mFac.size = hdr->fac().size(); mSac.offset = hdr->sac().offset(); @@ -148,13 +207,54 @@ void AciHeader::importBinary(const u8 * bytes) mKc.size = hdr->kc().size(); } -void AciHeader::importBinary(const u8 * bytes, size_t len) +void nx::AciHeader::clear() { - if (len < sizeof(sAciHeader)) - { - throw fnd::Exception(kModuleName, "ACI header too small"); - } - importBinary(bytes); + clearVariables(); +} + +size_t nx::AciHeader::getAciSize() const +{ + return MAX(MAX(MAX(mSac.offset + mSac.size, mKc.offset + mKc.size), mFac.offset + mFac.size), sizeof(sAciHeader)); +} + +u32 nx::AciHeader::getAcidVersion() const +{ + return mAcidVersion; +} + +void nx::AciHeader::setAcidVersion(u32 version) +{ + mAcidVersion = version; +} + +size_t nx::AciHeader::getAcidSize() const +{ + return mAcidSize; +} + +void nx::AciHeader::setAcidSize(size_t size) +{ + mAcidSize = size; +} + +u64 nx::AciHeader::getProgramIdMin() const +{ + return mProgramIdMin; +} + +void nx::AciHeader::setProgramIdMin(u64 program_id) +{ + mProgramIdMin = program_id; +} + +u64 nx::AciHeader::getProgramIdMax() const +{ + return mProgramIdMax; +} + +void nx::AciHeader::setProgramIdMax(u64 program_id) +{ + mProgramIdMax = program_id; } AciHeader::AciType AciHeader::getAciType() const @@ -177,32 +277,32 @@ void AciHeader::setProgramId(u64 program_id) mProgramId = program_id; } -const AciHeader::sSection & AciHeader::getFileAccessControl() const +const AciHeader::sSection & AciHeader::getFacPos() const { return mFac; } -void AciHeader::setFileAccessControl(u32 size) +void AciHeader::setFacSize(u32 size) { mFac.size = size; } -const AciHeader::sSection & AciHeader::getServiceAccessControl() const +const AciHeader::sSection & AciHeader::getSacPos() const { return mSac; } -void AciHeader::setServiceAccessControl(u32 size) +void AciHeader::setSacSize(u32 size) { mSac.size = size; } -const AciHeader::sSection & AciHeader::getKernelCapabilities() const +const AciHeader::sSection & AciHeader::getKcPos() const { return mKc; } -void AciHeader::setKernelCapabilities(u32 size) +void AciHeader::setKcSize(u32 size) { mKc.size = size; } diff --git a/lib/nx/AciHeader.h b/lib/nx/AciHeader.h index f7d136f..5b76642 100644 --- a/lib/nx/AciHeader.h +++ b/lib/nx/AciHeader.h @@ -40,7 +40,7 @@ namespace nx AciHeader(); AciHeader(const AciHeader& other); - AciHeader(const u8* bytes); + AciHeader(const u8* bytes, size_t len); bool operator==(const AciHeader& other) const; bool operator!=(const AciHeader& other) const; @@ -51,21 +51,36 @@ namespace nx size_t getSize() const; // export/import binary - void exportBinary(); - void importBinary(const u8* bytes); - void importBinary(const u8* bytes, size_t len); + virtual void exportBinary(); + virtual void importBinary(const u8* bytes, size_t len); // variables - AciType getAciType() const; - void setAciType(AciType type); + virtual void clear(); + size_t getAciSize() const; + + // ACI0 only u64 getProgramId() const; void setProgramId(u64 program_id); - const sSection& getFileAccessControl() const; - void setFileAccessControl(u32 size); - const sSection& getServiceAccessControl() const; - void setServiceAccessControl(u32 size); - const sSection& getKernelCapabilities() const; - void setKernelCapabilities(u32 size); + + // ACID only + u32 getAcidVersion() const; + void setAcidVersion(u32 version); + size_t getAcidSize() const; + void setAcidSize(size_t size); + u64 getProgramIdMin() const; + void setProgramIdMin(u64 program_id); + u64 getProgramIdMax() const; + void setProgramIdMax(u64 program_id); + + // ACID & ACI0 + AciType getAciType() const; + void setAciType(AciType type); + const sSection& getFacPos() const; + void setFacSize(u32 size); + const sSection& getSacPos() const; + void setSacSize(u32 size); + const sSection& getKcPos() const; + void setKcSize(u32 size); private: const std::string kModuleName = "ACI_HEADER"; @@ -79,9 +94,10 @@ namespace nx private: u8 signature_[4]; u32 size_; // includes prefacing signature, set only in ACID since it is signed - u8 reserved_1[8]; + u32 version_; // set in ACID only, v0 has size, but no pid range, v1 has no size by pid range + u8 reserved_1[4]; u64 program_id_; // set only in ACI0 (since ACID is generic) - u8 reserved_2[8]; + u64 program_id_max_; struct sAciSection { private: @@ -93,8 +109,7 @@ namespace nx u32 size() const { return le_word(size_); } void set_size(u32 size) { size_ = le_word(size); } - } fac_, sac_, kc_; - u8 reserved_3[8]; + } fac_, sac_, kc_, reserved_3; public: const char* signature() const { return (const char*)signature_; } void set_signature(const char* signature) { memcpy(signature_, signature, 4); } @@ -102,9 +117,18 @@ namespace nx u32 size() const { return le_word(size_); } void set_size(u32 size) { size_ = le_word(size); } + u32 version() const { return le_word(version_); } + void set_version(u32 version) { version_ = le_word(version); } + u64 program_id() const { return le_dword(program_id_); } void set_program_id(u64 program_id) { program_id_ = le_dword(program_id); } + u64 program_id_min() const { return program_id(); } + void set_program_id_min(u64 program_id) { set_program_id(program_id); } + + u64 program_id_max() const { return le_dword(program_id_max_); } + void set_program_id_max(u64 program_id) { program_id_max_ = le_dword(program_id); } + const sAciSection& fac() const { return fac_; } sAciSection& fac() { return fac_; } @@ -119,9 +143,17 @@ namespace nx // raw data fnd::MemoryBlob mBinaryBlob; - // variables - AciType mType; + // ACI variables u64 mProgramId; + + // ACID variables + u32 mAcidVersion; + size_t mAcidSize; + u64 mProgramIdMin; + u64 mProgramIdMax; + + // ACI(D) variables + AciType mType; sSection mFac, mSac, mKc; void clearVariables(); diff --git a/lib/nx/FacBinary.cpp b/lib/nx/FacBinary.cpp index 88923ed..778a546 100644 --- a/lib/nx/FacBinary.cpp +++ b/lib/nx/FacBinary.cpp @@ -66,11 +66,6 @@ void FacBinary::exportBinary() } } -void FacBinary::importBinary(const u8 * bytes) -{ - throw fnd::Exception(kModuleName, "Unsupported operation. importBinary(const u8* bytes) is not supported for variable size structures."); -} - void FacBinary::importBinary(const u8 * bytes, size_t len) { clearVariables(); @@ -99,6 +94,11 @@ void FacBinary::importBinary(const u8 * bytes, size_t len) } } +void nx::FacBinary::clear() +{ + clearVariables(); +} + bool FacBinary::isPermissionSet(FsAccessFlag flag) const { return (mFsaRights & flag) == flag; diff --git a/lib/nx/FacBinary.h b/lib/nx/FacBinary.h index 1305a9b..e15af88 100644 --- a/lib/nx/FacBinary.h +++ b/lib/nx/FacBinary.h @@ -51,10 +51,10 @@ namespace nx // export/import binary void exportBinary(); - void importBinary(const u8* bytes); void importBinary(const u8* bytes, size_t len); // variables + void clear(); bool isPermissionSet(FsAccessFlag flag) const; void addPermission(FsAccessFlag flag); void removePermission(FsAccessFlag flag); diff --git a/lib/nx/FacHeader.cpp b/lib/nx/FacHeader.cpp index b34bf8f..e9f11aa 100644 --- a/lib/nx/FacHeader.cpp +++ b/lib/nx/FacHeader.cpp @@ -1,48 +1,48 @@ #include "FacHeader.h" -using namespace nx; -FacHeader::FacHeader() + +nx::FacHeader::FacHeader() { clearVariables(); } -FacHeader::FacHeader(const FacHeader & other) +nx::FacHeader::FacHeader(const FacHeader & other) { copyFrom(other); } -FacHeader::FacHeader(const u8 * bytes) +nx::FacHeader::FacHeader(const u8 * bytes, size_t len) { - importBinary(bytes); + importBinary(bytes, len); } -bool FacHeader::operator==(const FacHeader & other) const +bool nx::FacHeader::operator==(const FacHeader & other) const { return isEqual(other); } -bool FacHeader::operator!=(const FacHeader & other) const +bool nx::FacHeader::operator!=(const FacHeader & other) const { return !isEqual(other); } -void FacHeader::operator=(const FacHeader & other) +void nx::FacHeader::operator=(const FacHeader & other) { copyFrom(other); } -const u8 * FacHeader::getBytes() const +const u8 * nx::FacHeader::getBytes() const { return mBinaryBlob.getBytes(); } -size_t FacHeader::getSize() const +size_t nx::FacHeader::getSize() const { return mBinaryBlob.getSize(); } -void FacHeader::exportBinary() +void nx::FacHeader::exportBinary() { mBinaryBlob.alloc(sizeof(sFacHeader)); sFacHeader* hdr = (sFacHeader*)mBinaryBlob.getBytes(); @@ -57,8 +57,13 @@ void FacHeader::exportBinary() hdr->save_data_owner_ids().set_end(mSaveDataOwnerIdPos.offset + mSaveDataOwnerIdPos.size); } -void FacHeader::importBinary(const u8 * bytes) +void nx::FacHeader::importBinary(const u8 * bytes, size_t len) { + if (len < sizeof(sFacHeader)) + { + throw fnd::Exception(kModuleName, "FAC header too small"); + } + mBinaryBlob.alloc(sizeof(sFacHeader)); memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); sFacHeader* hdr = (sFacHeader*)mBinaryBlob.getBytes(); @@ -70,66 +75,64 @@ void FacHeader::importBinary(const u8 * bytes) mFsaRights = hdr->fac_flags(); mContentOwnerIdPos.offset = hdr->content_owner_ids().start(); - mContentOwnerIdPos.size = hdr->content_owner_ids().end() - hdr->content_owner_ids().start(); + mContentOwnerIdPos.size = hdr->content_owner_ids().end() > hdr->content_owner_ids().start() ? hdr->content_owner_ids().end() - hdr->content_owner_ids().start() : 0; mSaveDataOwnerIdPos.offset = hdr->save_data_owner_ids().start(); - mSaveDataOwnerIdPos.size = hdr->save_data_owner_ids().end() - hdr->save_data_owner_ids().start(); + mSaveDataOwnerIdPos.size = hdr->save_data_owner_ids().end() > hdr->save_data_owner_ids().start() ? hdr->save_data_owner_ids().end() - hdr->save_data_owner_ids().start() : 0; } -void FacHeader::importBinary(const u8 * bytes, size_t len) +void nx::FacHeader::clear() { - if (len < sizeof(sFacHeader)) - { - throw fnd::Exception(kModuleName, "FAC header too small"); - } - importBinary(bytes); + clearVariables(); } -u64 FacHeader::getFacSize() const +size_t nx::FacHeader::getFacSize() const { - return MAX(getSaveDataOwnerIdOffset() + getSaveDataOwnerIdSize(), getContentOwnerIdOffset() + getContentOwnerIdSize()); + size_t savedata = getSaveDataOwnerIdOffset() + getSaveDataOwnerIdSize(); + size_t content = getContentOwnerIdOffset() + getContentOwnerIdSize(); + return MAX(MAX(savedata, content), sizeof(sFacHeader)); } -u64 FacHeader::getFsaRights() const +u64 nx::FacHeader::getFsaRights() const { return mFsaRights; } -void FacHeader::setFsaRights(u64 flag) +void nx::FacHeader::setFsaRights(u64 flag) { mFsaRights = flag; } -size_t FacHeader::getContentOwnerIdOffset() const +size_t nx::FacHeader::getContentOwnerIdOffset() const { return mContentOwnerIdPos.offset; } -size_t FacHeader::getContentOwnerIdSize() const +size_t nx::FacHeader::getContentOwnerIdSize() const { return mContentOwnerIdPos.size; } -void FacHeader::setContentOwnerIdSize(size_t size) +void nx::FacHeader::setContentOwnerIdSize(size_t size) { mContentOwnerIdPos.size = size; } -size_t FacHeader::getSaveDataOwnerIdOffset() const +size_t nx::FacHeader::getSaveDataOwnerIdOffset() const { return mSaveDataOwnerIdPos.offset; } -size_t FacHeader::getSaveDataOwnerIdSize() const +size_t nx::FacHeader::getSaveDataOwnerIdSize() const { return mSaveDataOwnerIdPos.size; } -void FacHeader::setSaveDataOwnerIdSize(size_t size) +void nx::FacHeader::setSaveDataOwnerIdSize(size_t size) { mSaveDataOwnerIdPos.size = size; } -void FacHeader::clearVariables() +void nx::FacHeader::clearVariables() { mFsaRights = 0; mContentOwnerIdPos.offset = 0; @@ -138,13 +141,13 @@ void FacHeader::clearVariables() mSaveDataOwnerIdPos.size = 0; } -void FacHeader::calculateOffsets() +void nx::FacHeader::calculateOffsets() { mContentOwnerIdPos.offset = align(sizeof(sFacHeader), 4); mSaveDataOwnerIdPos.offset = mContentOwnerIdPos.offset + align(mContentOwnerIdPos.size, 4); } -bool FacHeader::isEqual(const FacHeader & other) const +bool nx::FacHeader::isEqual(const FacHeader & other) const { return (mFsaRights == other.mFsaRights) \ && (mContentOwnerIdPos.offset == other.mContentOwnerIdPos.offset) \ @@ -153,7 +156,7 @@ bool FacHeader::isEqual(const FacHeader & other) const && (mSaveDataOwnerIdPos.size == other.mSaveDataOwnerIdPos.size); } -void FacHeader::copyFrom(const FacHeader & other) +void nx::FacHeader::copyFrom(const FacHeader & other) { if (other.getSize()) { diff --git a/lib/nx/FacHeader.h b/lib/nx/FacHeader.h index b00510f..5ffed50 100644 --- a/lib/nx/FacHeader.h +++ b/lib/nx/FacHeader.h @@ -11,7 +11,7 @@ namespace nx public: FacHeader(); FacHeader(const FacHeader& other); - FacHeader(const u8* bytes); + FacHeader(const u8* bytes, size_t len); bool operator==(const FacHeader& other) const; bool operator!=(const FacHeader& other) const; @@ -23,11 +23,11 @@ namespace nx // export/import binary void exportBinary(); - void importBinary(const u8* bytes); void importBinary(const u8* bytes, size_t len); // variables - u64 getFacSize() const; + void clear(); + size_t getFacSize() const; u64 getFsaRights() const; void setFsaRights(u64 flag); diff --git a/lib/nx/ISerialiseableBinary.h b/lib/nx/ISerialiseableBinary.h index 9dcb807..1160464 100644 --- a/lib/nx/ISerialiseableBinary.h +++ b/lib/nx/ISerialiseableBinary.h @@ -13,8 +13,9 @@ namespace nx virtual size_t getSize() const = 0; virtual void exportBinary() = 0; - virtual void importBinary(const u8* bytes) = 0; virtual void importBinary(const u8* bytes, size_t len) = 0; + + virtual void clear() = 0; }; } diff --git a/lib/nx/InteruptHandler.cpp b/lib/nx/InteruptHandler.cpp index 85b1498..346a519 100644 --- a/lib/nx/InteruptHandler.cpp +++ b/lib/nx/InteruptHandler.cpp @@ -24,6 +24,9 @@ void nx::InteruptHandler::operator=(const InteruptHandler & other) void nx::InteruptHandler::importKernelCapabilityList(const fnd::List& caps) { + if (caps.getSize() == 0) + return; + // convert to interupts fnd::List interupts; for (size_t i = 0; i < caps.getSize(); i++) @@ -92,12 +95,12 @@ bool nx::InteruptHandler::isSet() const return mIsSet; } -const fnd::List& nx::InteruptHandler::getInterupts() const +const fnd::List& nx::InteruptHandler::getInteruptList() const { return mInterupts; } -void nx::InteruptHandler::setInterupts(const fnd::List& interupts) +void nx::InteruptHandler::setInteruptList(const fnd::List& interupts) { mInterupts.clear(); for (size_t i = 0; i < interupts.getSize(); i++) diff --git a/lib/nx/InteruptHandler.h b/lib/nx/InteruptHandler.h index d4a8603..1700954 100644 --- a/lib/nx/InteruptHandler.h +++ b/lib/nx/InteruptHandler.h @@ -21,8 +21,8 @@ namespace nx bool isSet() const; // variables - const fnd::List& getInterupts() const; - void setInterupts(const fnd::List& interupts); + const fnd::List& getInteruptList() const; + void setInteruptList(const fnd::List& interupts); private: const std::string kModuleName = "INTERUPT_HANDLER"; diff --git a/lib/nx/KcBinary.cpp b/lib/nx/KcBinary.cpp index c4b9a69..ee2baa7 100644 --- a/lib/nx/KcBinary.cpp +++ b/lib/nx/KcBinary.cpp @@ -65,11 +65,6 @@ void nx::KcBinary::exportBinary() } } -void nx::KcBinary::importBinary(const u8 * bytes) -{ - throw fnd::Exception(kModuleName, "Unsupported operation. importBinary(const u8* bytes) is not supported for variable size structures."); -} - void nx::KcBinary::importBinary(const u8 * bytes, size_t len) { if ((len % sizeof(u32)) != 0) @@ -134,6 +129,11 @@ void nx::KcBinary::importBinary(const u8 * bytes, size_t len) mMiscFlags.importKernelCapabilityList(miscFlagsCaps); } +void nx::KcBinary::clear() +{ + clearVariables(); +} + const nx::ThreadInfoHandler & nx::KcBinary::getThreadInfo() const { return mThreadInfo; diff --git a/lib/nx/KcBinary.h b/lib/nx/KcBinary.h index 975b080..6f9147d 100644 --- a/lib/nx/KcBinary.h +++ b/lib/nx/KcBinary.h @@ -33,10 +33,10 @@ namespace nx // export/import binary void exportBinary(); - void importBinary(const u8* bytes); void importBinary(const u8* bytes, size_t len); // variables (consider further abstraction?) + void clear(); const ThreadInfoHandler& getThreadInfo() const; ThreadInfoHandler& getThreadInfo(); diff --git a/lib/nx/MemoryMappingHandler.cpp b/lib/nx/MemoryMappingHandler.cpp index 4cb802e..17d771f 100644 --- a/lib/nx/MemoryMappingHandler.cpp +++ b/lib/nx/MemoryMappingHandler.cpp @@ -23,8 +23,11 @@ void nx::MemoryMappingHandler::operator=(const MemoryMappingHandler & other) void nx::MemoryMappingHandler::importKernelCapabilityList(const fnd::List& caps) { - fnd::List entries; + if (caps.getSize() == 0) + return; + // get entry list + fnd::List entries; for (size_t i = 0; i < caps.getSize(); i++) { entries[i].setKernelCapability(caps[i]); @@ -32,7 +35,7 @@ void nx::MemoryMappingHandler::importKernelCapabilityList(const fnd::List& caps) { if (caps.getSize() > kMaxKernelCapNum) @@ -16,8 +31,18 @@ void nx::MiscFlagsHandler::importKernelCapabilityList(const fnd::List& nx::MiscFlagsHandler::getFlagList() const { - return mEntry.getFlags(); + return mFlags; } -void nx::MiscFlagsHandler::setFlags(u32 flags) +void nx::MiscFlagsHandler::setFlagList(fnd::List flags) { - mEntry.setFlags(flags); + mFlags = flags; mIsSet = true; } void nx::MiscFlagsHandler::copyFrom(const MiscFlagsHandler & other) { mIsSet = other.mIsSet; - mEntry.setKernelCapability(other.mEntry.getKernelCapability()); + mFlags = other.mFlags; } bool nx::MiscFlagsHandler::isEqual(const MiscFlagsHandler & other) const { return (mIsSet == other.mIsSet) \ - && (mEntry.getKernelCapability() == other.mEntry.getKernelCapability()); + && (mFlags == other.mFlags); } diff --git a/lib/nx/MiscFlagsHandler.h b/lib/nx/MiscFlagsHandler.h index 905f4cb..124ce45 100644 --- a/lib/nx/MiscFlagsHandler.h +++ b/lib/nx/MiscFlagsHandler.h @@ -10,21 +10,22 @@ namespace nx public: enum Flags { - FLAG_ENABLE_DEBUG = BIT(0), - FLAG_FORCE_DEBUG = BIT(1), - FLAG_UNK02 = BIT(2), - FLAG_UNK03 = BIT(3), - FLAG_UNK04 = BIT(4), - FLAG_UNK05 = BIT(5), - FLAG_UNK06 = BIT(6), - FLAG_UNK07 = BIT(7), - FLAG_UNK08 = BIT(8), - FLAG_UNK09 = BIT(9), - FLAG_UNK10 = BIT(10), - FLAG_UNK11 = BIT(11), - FLAG_UNK12 = BIT(12), - FLAG_UNK13 = BIT(13), - FLAG_UNK14 = BIT(14), + FLAG_ENABLE_DEBUG, + FLAG_FORCE_DEBUG, + FLAG_UNK02, + FLAG_UNK03, + FLAG_UNK04, + FLAG_UNK05, + FLAG_UNK06, + FLAG_UNK07, + FLAG_UNK08, + FLAG_UNK09, + FLAG_UNK10, + FLAG_UNK11, + FLAG_UNK12, + FLAG_UNK13, + FLAG_UNK14, + FLAG_NUM }; MiscFlagsHandler(); @@ -40,14 +41,15 @@ namespace nx bool isSet() const; // variables - u32 getFlags() const; - void setFlags(u32 flags); + const fnd::List& getFlagList() const; + void setFlagList(fnd::List flags); + private: const std::string kModuleName = "MISC_FLAGS_HANDLER"; static const size_t kMaxKernelCapNum = 1; bool mIsSet; - MiscFlagsEntry mEntry; + fnd::List mFlags; void copyFrom(const MiscFlagsHandler& other); bool isEqual(const MiscFlagsHandler& other) const; diff --git a/lib/nx/NcaHeader.cpp b/lib/nx/NcaHeader.cpp index 755adf0..426d306 100644 --- a/lib/nx/NcaHeader.cpp +++ b/lib/nx/NcaHeader.cpp @@ -34,10 +34,15 @@ void NcaHeader::exportBinary() } } -void NcaHeader::importBinary(const u8 * bytes) +void NcaHeader::importBinary(const u8 * bytes, size_t len) { + if (len < sizeof(sNcaHeader)) + { + throw fnd::Exception(kModuleName, "NCA header size is too small"); + } + clearVariables(); - + mBinaryBlob.alloc(sizeof(sNcaHeader)); memcpy(mBinaryBlob.getBytes(), bytes, sizeof(sNcaHeader)); @@ -47,7 +52,7 @@ void NcaHeader::importBinary(const u8 * bytes) { throw fnd::Exception(kModuleName, "NCA header corrupt"); } - + mBlockSize = hdr->block_size(); mNcaSize = hdr->nca_size(); mProgramId = hdr->program_id(); @@ -57,10 +62,10 @@ void NcaHeader::importBinary(const u8 * bytes) { // determine section index u8 section = kSectionNum - 1 - i; - + // skip sections that don't exist if (hdr->section(section).start() == 0 && hdr->section(section).end() == 0) continue; - + // add high level struct mSections.addElement({ blockNumToSize(hdr->section(section).start()), blockNumToSize(hdr->section(section).end() - hdr->section(section).start()), hdr->section(section).key_type(), hdr->section_hash(section) }); } @@ -71,13 +76,9 @@ void NcaHeader::importBinary(const u8 * bytes) } } -void NcaHeader::importBinary(const u8 * bytes, size_t len) +void nx::NcaHeader::clear() { - if (len < sizeof(sNcaHeader)) - { - throw fnd::Exception(kModuleName, "NCA header size is too small"); - } - importBinary(bytes); + clearVariables(); } u64 NcaHeader::getNcaSize() const @@ -192,9 +193,9 @@ NcaHeader::NcaHeader(const NcaHeader & other) copyFrom(other); } -NcaHeader::NcaHeader(const u8 * bytes) +NcaHeader::NcaHeader(const u8 * bytes, size_t len) { - importBinary(bytes); + importBinary(bytes, len); } bool NcaHeader::operator==(const NcaHeader & other) const diff --git a/lib/nx/NcaHeader.h b/lib/nx/NcaHeader.h index cb47f0b..e8c22de 100644 --- a/lib/nx/NcaHeader.h +++ b/lib/nx/NcaHeader.h @@ -47,7 +47,7 @@ namespace nx NcaHeader(); NcaHeader(const NcaHeader& other); - NcaHeader(const u8* bytes); + NcaHeader(const u8* bytes, size_t len); bool operator==(const NcaHeader& other) const; bool operator!=(const NcaHeader& other) const; @@ -59,10 +59,10 @@ namespace nx // export/import binary void exportBinary(); - void importBinary(const u8* bytes); void importBinary(const u8* bytes, size_t len); // variables + void clear(); u64 getNcaSize() const; void setNcaSize(u64 size); u64 getProgramId() const; diff --git a/lib/nx/NpdmHeader.cpp b/lib/nx/NpdmHeader.cpp index 07385b6..c1e56e5 100644 --- a/lib/nx/NpdmHeader.cpp +++ b/lib/nx/NpdmHeader.cpp @@ -12,9 +12,9 @@ nx::NpdmHeader::NpdmHeader(const NpdmHeader & other) copyFrom(other); } -nx::NpdmHeader::NpdmHeader(const u8 * bytes) +nx::NpdmHeader::NpdmHeader(const u8 * bytes, size_t len) { - importBinary(bytes); + importBinary(bytes, len); } bool nx::NpdmHeader::operator==(const NpdmHeader & other) const @@ -122,8 +122,15 @@ void nx::NpdmHeader::exportBinary() hdr->acid().set_size(mAcidPos.size); } -void nx::NpdmHeader::importBinary(const u8 * bytes) +void nx::NpdmHeader::importBinary(const u8 * bytes, size_t len) { + if (len < sizeof(sNpdmHeader)) + { + throw fnd::Exception(kModuleName, "NPDM header too small"); + } + + clearVariables(); + mBinaryBlob.alloc(sizeof(sNpdmHeader)); memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); sNpdmHeader* hdr = (sNpdmHeader*)mBinaryBlob.getBytes(); @@ -148,13 +155,9 @@ void nx::NpdmHeader::importBinary(const u8 * bytes) mAcidPos.size = hdr->acid().size(); } -void nx::NpdmHeader::importBinary(const u8 * bytes, size_t len) +void nx::NpdmHeader::clear() { - if (len < sizeof(sNpdmHeader)) - { - throw fnd::Exception(kModuleName, "NPDM header too small"); - } - importBinary(bytes); + clearVariables(); } size_t nx::NpdmHeader::getNpdmSize() const diff --git a/lib/nx/NpdmHeader.h b/lib/nx/NpdmHeader.h index ecb622b..2b49249 100644 --- a/lib/nx/NpdmHeader.h +++ b/lib/nx/NpdmHeader.h @@ -49,7 +49,7 @@ namespace nx NpdmHeader(); NpdmHeader(const NpdmHeader& other); - NpdmHeader(const u8* bytes); + NpdmHeader(const u8* bytes, size_t len); bool operator==(const NpdmHeader& other) const; bool operator!=(const NpdmHeader& other) const; @@ -61,10 +61,10 @@ namespace nx // export/import binary void exportBinary(); - void importBinary(const u8* bytes); void importBinary(const u8* bytes, size_t len); // variables + void clear(); size_t getNpdmSize() const; InstructionType getInstructionType() const; diff --git a/lib/nx/SacBinary.cpp b/lib/nx/SacBinary.cpp index cc452a7..5f3170b 100644 --- a/lib/nx/SacBinary.cpp +++ b/lib/nx/SacBinary.cpp @@ -57,11 +57,6 @@ void SacBinary::exportBinary() } } -void SacBinary::importBinary(const u8 * bytes) -{ - throw fnd::Exception(kModuleName, "Unsupported operation. importBinary(const u8* bytes) is not supported for variable size structures."); -} - void SacBinary::importBinary(const u8 * bytes, size_t len) { clearVariables(); @@ -76,6 +71,11 @@ void SacBinary::importBinary(const u8 * bytes, size_t len) } } +void nx::SacBinary::clear() +{ + clearVariables(); +} + const fnd::List& SacBinary::getServiceList() const { return mServices; diff --git a/lib/nx/SacBinary.h b/lib/nx/SacBinary.h index ed87936..4fd3a5b 100644 --- a/lib/nx/SacBinary.h +++ b/lib/nx/SacBinary.h @@ -26,10 +26,10 @@ namespace nx // export/import binary void exportBinary(); - void importBinary(const u8* bytes); void importBinary(const u8* bytes, size_t len); // variables + void clear(); const fnd::List& getServiceList() const; void addService(const SacEntry& service); private: diff --git a/lib/nx/SacEntry.cpp b/lib/nx/SacEntry.cpp index 994e8e3..b2065a5 100644 --- a/lib/nx/SacEntry.cpp +++ b/lib/nx/SacEntry.cpp @@ -55,25 +55,25 @@ void SacEntry::exportBinary() throw fnd::Exception(kModuleName, "Failed to allocate memory for SacEntry: " + std::string(e.what())); } + if (mName.length() == 0) + { + throw fnd::Exception(kModuleName, "Service name is empty"); + } + if (mName.length() > kMaxServiceNameLen) { throw fnd::Exception(kModuleName, "Service name string too long (max 8 chars)"); } // copy data into binary blob - mBinaryBlob[0] = (mIsServer ? SAC_IS_SERVER : 0) | (mName.length() & SAC_NAME_LEN_MASK); + mBinaryBlob[0] = (mIsServer ? SAC_IS_SERVER : 0) | ((mName.length()-1) & SAC_NAME_LEN_MASK); // bug? memcpy(mBinaryBlob.getBytes() + 1, mName.c_str(), mName.length()); } -void SacEntry::importBinary(const u8 * bytes) -{ - throw fnd::Exception(kModuleName, "Unsupported operation. importBinary(const u8* bytes) is not supported for variable size structures."); -} - void SacEntry::importBinary(const u8 * bytes, size_t len) { bool isServer = (bytes[0] & SAC_IS_SERVER) == SAC_IS_SERVER; - size_t nameLen = (bytes[0] & SAC_NAME_LEN_MASK); + size_t nameLen = (bytes[0] & SAC_NAME_LEN_MASK) + 1; // bug? if (nameLen+1 > len) { @@ -96,6 +96,12 @@ void SacEntry::importBinary(const u8 * bytes, size_t len) mName = std::string((const char*)(mBinaryBlob.getBytes() + 1), nameLen); } +void nx::SacEntry::clear() +{ + mIsServer = false; + mName.clear(); +} + bool SacEntry::isServer() const { return mIsServer; diff --git a/lib/nx/SacEntry.h b/lib/nx/SacEntry.h index 7e1878b..d50c706 100644 --- a/lib/nx/SacEntry.h +++ b/lib/nx/SacEntry.h @@ -23,10 +23,10 @@ namespace nx // export/import binary void exportBinary(); - void importBinary(const u8* bytes); void importBinary(const u8* bytes, size_t len); // variables + void clear(); bool isServer() const; void setIsServer(bool isServer); const std::string& getName() const; diff --git a/lib/nx/SystemCallEntry.h b/lib/nx/SystemCallEntry.h index 222ae4b..4e94229 100644 --- a/lib/nx/SystemCallEntry.h +++ b/lib/nx/SystemCallEntry.h @@ -26,7 +26,7 @@ namespace nx const std::string kModuleName = "SYSTEM_CALL_ENTRY"; static const KernelCapability::KernelCapId kCapId = KernelCapability::KC_ENABLE_SYSTEM_CALLS; static const u32 kSysCallUpperBits = 3; - static const u32 kSysCallLowerBits = 23; + static const u32 kSysCallLowerBits = 24; static const u32 kSysCallUpperMax = BIT(kSysCallUpperBits) - 1; static const u32 kSysCallLowerMax = BIT(kSysCallLowerBits) - 1; diff --git a/lib/nx/SystemCallHandler.cpp b/lib/nx/SystemCallHandler.cpp index 148d24e..ed86344 100644 --- a/lib/nx/SystemCallHandler.cpp +++ b/lib/nx/SystemCallHandler.cpp @@ -24,18 +24,19 @@ void nx::SystemCallHandler::operator=(const SystemCallHandler & other) void nx::SystemCallHandler::importKernelCapabilityList(const fnd::List& caps) { + if (caps.getSize() == 0) + return; + SystemCallEntry entry; u8 syscallUpper, syscall; for (size_t i = 0; i < caps.getSize(); i++) { entry.setKernelCapability(caps[i]); - syscallUpper = 24 * entry.getSystemCallUpperBits(); for (u8 j = 0; j < 24; j++) { syscall = syscallUpper + j; - if (((entry.getSystemCallLowerBits() >> j) & 1) == 1) { mSystemCalls.hasElement(syscall) == false ? mSystemCalls.addElement(syscall) : throw fnd::Exception(kModuleName, "SystemCall already added"); @@ -94,7 +95,7 @@ const fnd::List& nx::SystemCallHandler::getSystemCalls() const return mSystemCalls; } -void nx::SystemCallHandler::setSystemCalls(const fnd::List& calls) +void nx::SystemCallHandler::setSystemCallList(const fnd::List& calls) { mSystemCalls.clear(); for (size_t i = 0; i < calls.getSize(); i++) diff --git a/lib/nx/SystemCallHandler.h b/lib/nx/SystemCallHandler.h index 99f2861..ef3d9fa 100644 --- a/lib/nx/SystemCallHandler.h +++ b/lib/nx/SystemCallHandler.h @@ -21,7 +21,7 @@ namespace nx // variables const fnd::List& getSystemCalls() const; - void setSystemCalls(const fnd::List& calls); + void setSystemCallList(const fnd::List& calls); private: const std::string kModuleName = "SYSTEM_CALL_HANDLER"; diff --git a/programs/ncatool/main.cpp b/programs/ncatool/main.cpp index a0cfd1e..68f3f45 100644 --- a/programs/ncatool/main.cpp +++ b/programs/ncatool/main.cpp @@ -70,7 +70,7 @@ int main(int argc, char** argv) decryptNcaSectorXts(nca, sector, 1, crypto::aes::nx::nca_header_key[0], crypto::aes::nx::nca_header_key[1]); nx::NcaHeader hdr; - hdr.importBinary(sector); + hdr.importBinary(sector, kNcaSectorSize); printf("[NCA Header]\n"); printf(" Size: 0x%" PRIx64 "\n", hdr.getNcaSize());