diff --git a/lib/nx/AciHeader.cpp b/lib/nx/AciHeader.cpp new file mode 100644 index 0000000..ae54d56 --- /dev/null +++ b/lib/nx/AciHeader.cpp @@ -0,0 +1,142 @@ +#include "AciHeader.h" + +void AciHeader::clearVariables() +{ + mType = TYPE_ACI0; + mProgramId = 0; + mFac.offset = 0; + mFac.size = 0; + mSac.offset = 0; + mSac.size = 0; + mKc.offset = 0; + mKc.size = 0; +} + +void AciHeader::calculateSectionOffsets() +{ + mFac.offset = align(sizeof(sAciHeader), kAciAlignSize); + mSac.offset = mFac.offset + align(mFac.size, kAciAlignSize); + mKc.offset = mSac.offset + align(mSac.size, kAciAlignSize); +} + +const u8 * AciHeader::getBytes() const +{ + return mBinaryBlob.data(); +} + +size_t AciHeader::getSize() const +{ + return mBinaryBlob.size(); +} + +void AciHeader::exportBinary() +{ + mBinaryBlob.alloc(sizeof(sAciHeader)); + sAciHeader* hdr = (sAciHeader*)mBinaryBlob.data(); + + // set type + switch (mType) + { + case (TYPE_ACI0): + hdr->set_signature(kAciStructSig.c_str()); + break; + case (TYPE_ACID): + hdr->set_signature(kAciDescStructSig.c_str()); + break; + default: + throw fnd::Exception(kModuleName, "Unexpected ACI type"); + } + + // set program + hdr->set_program_id(mProgramId); + + // set offset/size + calculateSectionOffsets(); + hdr->fac().set_offset(mFac.offset); + hdr->fac().set_size(mFac.size); + hdr->sac().set_offset(mSac.offset); + hdr->sac().set_size(mSac.size); + hdr->kc().set_offset(mKc.offset); + hdr->kc().set_size(mKc.size); +} + +void AciHeader::importBinary(const u8 * bytes) +{ + clearVariables(); + + mBinaryBlob.alloc(sizeof(sAciHeader)); + memcpy(mBinaryBlob.data(), bytes, sizeof(sAciHeader)); + + sAciHeader* hdr = (sAciHeader*)mBinaryBlob.data(); + + if (memcmp(hdr->signature(), kAciStructSig.c_str(), 4) == 0) + { + mType = TYPE_ACI0; + } + else if (memcmp(hdr->signature(), kAciDescStructSig.c_str(), 4) == 0) + { + mType = TYPE_ACID; + } + else + { + throw fnd::Exception(kModuleName, "ACI header corrupt"); + } + + mProgramId = hdr->program_id(); + mFac.offset = hdr->fac().offset(); + mFac.size = hdr->fac().size(); + mSac.offset = hdr->sac().offset(); + mSac.size = hdr->sac().size(); + mKc.offset = hdr->kc().offset(); + mKc.size = hdr->kc().size(); +} + +AciHeader::AciType AciHeader::getAciType() const +{ + return mType; +} + +void AciHeader::setAciType(AciType type) +{ + mType = type; +} + +u64 AciHeader::getProgramId() const +{ + return mProgramId; +} + +void AciHeader::setProgramId(u64 program_id) +{ + mProgramId = program_id; +} + +const AciHeader::sSection & AciHeader::getFileAccessControl() const +{ + return mFac; +} + +void AciHeader::setFileAccessControl(u32 size) +{ + mFac.size = size; +} + +const AciHeader::sSection & AciHeader::getServiceAccessControl() const +{ + return mSac; +} + +void AciHeader::setServiceAccessControl(u32 size) +{ + mSac.size = size; +} + +const AciHeader::sSection & AciHeader::getKernelCapabilities() const +{ + return mKc; +} + +void AciHeader::setKernelCapabilities(u32 size) +{ + mKc.size = size; +} diff --git a/lib/nx/AciHeader.h b/lib/nx/AciHeader.h new file mode 100644 index 0000000..101baac --- /dev/null +++ b/lib/nx/AciHeader.h @@ -0,0 +1,97 @@ +#pragma once +#include +#include +#include + +class AciHeader +{ +public: + enum AciType + { + TYPE_ACI0, // for Access Control Info + TYPE_ACID // for Access Control Info Desc + }; + + struct sSection + { + size_t offset; + size_t size; + }; + + // to be used after export + const u8* getBytes() const; + size_t getSize() const; + + // export/import binary + void exportBinary(); + void importBinary(const u8* bytes); + + // variables + AciType getAciType() const; + void setAciType(AciType type); + 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); + +private: + const std::string kModuleName = "ACI_HEADER"; + const std::string kAciStructSig = "ACI0"; + const std::string kAciDescStructSig = "ACID"; + static const size_t kAciAlignSize = 0x10; + +#pragma pack(push, 1) + struct sAciHeader + { + private: + u8 signature_[4]; + u8 reserved_1[12]; + u64 program_id_; + u8 reserved_2[8]; + struct sAciSection + { + private: + u32 offset_; // aligned by 0x10 from the last one + u32 size_; + public: + u32 offset() const { return le_word(offset_); } + void set_offset(u32 offset) { offset_ = le_word(offset); } + + u32 size() const { return le_word(size_); } + void set_size(u32 size) { size_ = le_word(size); } + } fac_, sac_, kc_; + u8 reserved_3[8]; + public: + const char* signature() const { return (const char*)signature_; } + void set_signature(const char* signature) { memcpy(signature_, signature, 4); } + + u64 program_id() const { return le_dword(program_id_); } + void set_program_id(u64 program_id) { program_id_ = le_dword(program_id); } + + const sAciSection& fac() const { return fac_; } + sAciSection& fac() { return fac_; } + + const sAciSection& sac() const { return sac_; } + sAciSection& sac() { return sac_; } + + const sAciSection& kc() const { return kc_; } + sAciSection& kc() { return kc_; } + }; +#pragma pack(pop) + + // raw data + fnd::MemoryBlob mBinaryBlob; + + // variables + AciType mType; + u64 mProgramId; + sSection mFac, mSac, mKc; + + void clearVariables(); + void calculateSectionOffsets(); +}; + diff --git a/lib/nx/nx.vcxproj b/lib/nx/nx.vcxproj index d525d0f..0969761 100644 --- a/lib/nx/nx.vcxproj +++ b/lib/nx/nx.vcxproj @@ -19,10 +19,12 @@ + + @@ -83,6 +85,7 @@ Level3 Disabled true + ..\ @@ -90,6 +93,7 @@ Level3 Disabled true + ..\ diff --git a/lib/nx/nx.vcxproj.filters b/lib/nx/nx.vcxproj.filters index 8885ede..a1a9994 100644 --- a/lib/nx/nx.vcxproj.filters +++ b/lib/nx/nx.vcxproj.filters @@ -21,10 +21,16 @@ Header Files + + Header Files + Source Files + + Source Files + \ No newline at end of file