mirror of
https://github.com/jakcron/nstool
synced 2024-11-22 21:49:30 +00:00
[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.
This commit is contained in:
parent
cb91fea97f
commit
20b4984ae3
26 changed files with 357 additions and 165 deletions
|
@ -24,6 +24,7 @@ void AciHeader::calculateSectionOffsets()
|
||||||
bool AciHeader::isEqual(const AciHeader & other) const
|
bool AciHeader::isEqual(const AciHeader & other) const
|
||||||
{
|
{
|
||||||
return (mType == other.mType) \
|
return (mType == other.mType) \
|
||||||
|
&& (mAcidSize == other.mAcidSize) \
|
||||||
&& (mProgramId == other.mProgramId) \
|
&& (mProgramId == other.mProgramId) \
|
||||||
&& (mFac == other.mFac) \
|
&& (mFac == other.mFac) \
|
||||||
&& (mSac == other.mSac) \
|
&& (mSac == other.mSac) \
|
||||||
|
@ -39,6 +40,7 @@ void AciHeader::copyFrom(const AciHeader & other)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mType = other.mType;
|
mType = other.mType;
|
||||||
|
mAcidSize = other.mAcidSize;
|
||||||
mProgramId = other.mProgramId;
|
mProgramId = other.mProgramId;
|
||||||
mFac = other.mFac;
|
mFac = other.mFac;
|
||||||
mSac = other.mSac;
|
mSac = other.mSac;
|
||||||
|
@ -56,9 +58,9 @@ AciHeader::AciHeader(const AciHeader & other)
|
||||||
importBinary(other.getBytes(), other.getSize());
|
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
|
bool AciHeader::operator==(const AciHeader & other) const
|
||||||
|
@ -104,8 +106,31 @@ void AciHeader::exportBinary()
|
||||||
throw fnd::Exception(kModuleName, "Unexpected ACI type");
|
throw fnd::Exception(kModuleName, "Unexpected ACI type");
|
||||||
}
|
}
|
||||||
|
|
||||||
// set program
|
if (mType == TYPE_ACI0)
|
||||||
hdr->set_program_id(mProgramId);
|
{
|
||||||
|
// 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
|
// set offset/size
|
||||||
calculateSectionOffsets();
|
calculateSectionOffsets();
|
||||||
|
@ -117,8 +142,13 @@ void AciHeader::exportBinary()
|
||||||
hdr->kc().set_size(mKc.size);
|
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();
|
clearVariables();
|
||||||
|
|
||||||
mBinaryBlob.alloc(sizeof(sAciHeader));
|
mBinaryBlob.alloc(sizeof(sAciHeader));
|
||||||
|
@ -139,7 +169,36 @@ void AciHeader::importBinary(const u8 * bytes)
|
||||||
throw fnd::Exception(kModuleName, "ACI header corrupt");
|
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.offset = hdr->fac().offset();
|
||||||
mFac.size = hdr->fac().size();
|
mFac.size = hdr->fac().size();
|
||||||
mSac.offset = hdr->sac().offset();
|
mSac.offset = hdr->sac().offset();
|
||||||
|
@ -148,13 +207,54 @@ void AciHeader::importBinary(const u8 * bytes)
|
||||||
mKc.size = hdr->kc().size();
|
mKc.size = hdr->kc().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AciHeader::importBinary(const u8 * bytes, size_t len)
|
void nx::AciHeader::clear()
|
||||||
{
|
{
|
||||||
if (len < sizeof(sAciHeader))
|
clearVariables();
|
||||||
{
|
}
|
||||||
throw fnd::Exception(kModuleName, "ACI header too small");
|
|
||||||
}
|
size_t nx::AciHeader::getAciSize() const
|
||||||
importBinary(bytes);
|
{
|
||||||
|
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
|
AciHeader::AciType AciHeader::getAciType() const
|
||||||
|
@ -177,32 +277,32 @@ void AciHeader::setProgramId(u64 program_id)
|
||||||
mProgramId = program_id;
|
mProgramId = program_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AciHeader::sSection & AciHeader::getFileAccessControl() const
|
const AciHeader::sSection & AciHeader::getFacPos() const
|
||||||
{
|
{
|
||||||
return mFac;
|
return mFac;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AciHeader::setFileAccessControl(u32 size)
|
void AciHeader::setFacSize(u32 size)
|
||||||
{
|
{
|
||||||
mFac.size = size;
|
mFac.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AciHeader::sSection & AciHeader::getServiceAccessControl() const
|
const AciHeader::sSection & AciHeader::getSacPos() const
|
||||||
{
|
{
|
||||||
return mSac;
|
return mSac;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AciHeader::setServiceAccessControl(u32 size)
|
void AciHeader::setSacSize(u32 size)
|
||||||
{
|
{
|
||||||
mSac.size = size;
|
mSac.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AciHeader::sSection & AciHeader::getKernelCapabilities() const
|
const AciHeader::sSection & AciHeader::getKcPos() const
|
||||||
{
|
{
|
||||||
return mKc;
|
return mKc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AciHeader::setKernelCapabilities(u32 size)
|
void AciHeader::setKcSize(u32 size)
|
||||||
{
|
{
|
||||||
mKc.size = size;
|
mKc.size = size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace nx
|
||||||
|
|
||||||
AciHeader();
|
AciHeader();
|
||||||
AciHeader(const AciHeader& other);
|
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;
|
||||||
bool operator!=(const AciHeader& other) const;
|
bool operator!=(const AciHeader& other) const;
|
||||||
|
@ -51,21 +51,36 @@ namespace nx
|
||||||
size_t getSize() const;
|
size_t getSize() const;
|
||||||
|
|
||||||
// export/import binary
|
// export/import binary
|
||||||
void exportBinary();
|
virtual void exportBinary();
|
||||||
void importBinary(const u8* bytes);
|
virtual void importBinary(const u8* bytes, size_t len);
|
||||||
void importBinary(const u8* bytes, size_t len);
|
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
AciType getAciType() const;
|
virtual void clear();
|
||||||
void setAciType(AciType type);
|
size_t getAciSize() const;
|
||||||
|
|
||||||
|
// ACI0 only
|
||||||
u64 getProgramId() const;
|
u64 getProgramId() const;
|
||||||
void setProgramId(u64 program_id);
|
void setProgramId(u64 program_id);
|
||||||
const sSection& getFileAccessControl() const;
|
|
||||||
void setFileAccessControl(u32 size);
|
// ACID only
|
||||||
const sSection& getServiceAccessControl() const;
|
u32 getAcidVersion() const;
|
||||||
void setServiceAccessControl(u32 size);
|
void setAcidVersion(u32 version);
|
||||||
const sSection& getKernelCapabilities() const;
|
size_t getAcidSize() const;
|
||||||
void setKernelCapabilities(u32 size);
|
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:
|
private:
|
||||||
const std::string kModuleName = "ACI_HEADER";
|
const std::string kModuleName = "ACI_HEADER";
|
||||||
|
@ -79,9 +94,10 @@ namespace nx
|
||||||
private:
|
private:
|
||||||
u8 signature_[4];
|
u8 signature_[4];
|
||||||
u32 size_; // includes prefacing signature, set only in ACID since it is signed
|
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)
|
u64 program_id_; // set only in ACI0 (since ACID is generic)
|
||||||
u8 reserved_2[8];
|
u64 program_id_max_;
|
||||||
struct sAciSection
|
struct sAciSection
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -93,8 +109,7 @@ namespace nx
|
||||||
|
|
||||||
u32 size() const { return le_word(size_); }
|
u32 size() const { return le_word(size_); }
|
||||||
void set_size(u32 size) { size_ = le_word(size); }
|
void set_size(u32 size) { size_ = le_word(size); }
|
||||||
} fac_, sac_, kc_;
|
} fac_, sac_, kc_, reserved_3;
|
||||||
u8 reserved_3[8];
|
|
||||||
public:
|
public:
|
||||||
const char* signature() const { return (const char*)signature_; }
|
const char* signature() const { return (const char*)signature_; }
|
||||||
void set_signature(const char* signature) { memcpy(signature_, signature, 4); }
|
void set_signature(const char* signature) { memcpy(signature_, signature, 4); }
|
||||||
|
@ -102,9 +117,18 @@ namespace nx
|
||||||
u32 size() const { return le_word(size_); }
|
u32 size() const { return le_word(size_); }
|
||||||
void set_size(u32 size) { size_ = 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_); }
|
u64 program_id() const { return le_dword(program_id_); }
|
||||||
void set_program_id(u64 program_id) { program_id_ = 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_; }
|
const sAciSection& fac() const { return fac_; }
|
||||||
sAciSection& fac() { return fac_; }
|
sAciSection& fac() { return fac_; }
|
||||||
|
|
||||||
|
@ -119,9 +143,17 @@ namespace nx
|
||||||
// raw data
|
// raw data
|
||||||
fnd::MemoryBlob mBinaryBlob;
|
fnd::MemoryBlob mBinaryBlob;
|
||||||
|
|
||||||
// variables
|
// ACI variables
|
||||||
AciType mType;
|
|
||||||
u64 mProgramId;
|
u64 mProgramId;
|
||||||
|
|
||||||
|
// ACID variables
|
||||||
|
u32 mAcidVersion;
|
||||||
|
size_t mAcidSize;
|
||||||
|
u64 mProgramIdMin;
|
||||||
|
u64 mProgramIdMax;
|
||||||
|
|
||||||
|
// ACI(D) variables
|
||||||
|
AciType mType;
|
||||||
sSection mFac, mSac, mKc;
|
sSection mFac, mSac, mKc;
|
||||||
|
|
||||||
void clearVariables();
|
void clearVariables();
|
||||||
|
|
|
@ -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)
|
void FacBinary::importBinary(const u8 * bytes, size_t len)
|
||||||
{
|
{
|
||||||
clearVariables();
|
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
|
bool FacBinary::isPermissionSet(FsAccessFlag flag) const
|
||||||
{
|
{
|
||||||
return (mFsaRights & flag) == flag;
|
return (mFsaRights & flag) == flag;
|
||||||
|
|
|
@ -51,10 +51,10 @@ namespace nx
|
||||||
|
|
||||||
// export/import binary
|
// export/import binary
|
||||||
void exportBinary();
|
void exportBinary();
|
||||||
void importBinary(const u8* bytes);
|
|
||||||
void importBinary(const u8* bytes, size_t len);
|
void importBinary(const u8* bytes, size_t len);
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
|
void clear();
|
||||||
bool isPermissionSet(FsAccessFlag flag) const;
|
bool isPermissionSet(FsAccessFlag flag) const;
|
||||||
void addPermission(FsAccessFlag flag);
|
void addPermission(FsAccessFlag flag);
|
||||||
void removePermission(FsAccessFlag flag);
|
void removePermission(FsAccessFlag flag);
|
||||||
|
|
|
@ -1,48 +1,48 @@
|
||||||
#include "FacHeader.h"
|
#include "FacHeader.h"
|
||||||
|
|
||||||
using namespace nx;
|
|
||||||
|
|
||||||
FacHeader::FacHeader()
|
|
||||||
|
nx::FacHeader::FacHeader()
|
||||||
{
|
{
|
||||||
clearVariables();
|
clearVariables();
|
||||||
}
|
}
|
||||||
|
|
||||||
FacHeader::FacHeader(const FacHeader & other)
|
nx::FacHeader::FacHeader(const FacHeader & other)
|
||||||
{
|
{
|
||||||
copyFrom(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);
|
return isEqual(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FacHeader::operator!=(const FacHeader & other) const
|
bool nx::FacHeader::operator!=(const FacHeader & other) const
|
||||||
{
|
{
|
||||||
return !isEqual(other);
|
return !isEqual(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FacHeader::operator=(const FacHeader & other)
|
void nx::FacHeader::operator=(const FacHeader & other)
|
||||||
{
|
{
|
||||||
copyFrom(other);
|
copyFrom(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8 * FacHeader::getBytes() const
|
const u8 * nx::FacHeader::getBytes() const
|
||||||
{
|
{
|
||||||
return mBinaryBlob.getBytes();
|
return mBinaryBlob.getBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FacHeader::getSize() const
|
size_t nx::FacHeader::getSize() const
|
||||||
{
|
{
|
||||||
return mBinaryBlob.getSize();
|
return mBinaryBlob.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FacHeader::exportBinary()
|
void nx::FacHeader::exportBinary()
|
||||||
{
|
{
|
||||||
mBinaryBlob.alloc(sizeof(sFacHeader));
|
mBinaryBlob.alloc(sizeof(sFacHeader));
|
||||||
sFacHeader* hdr = (sFacHeader*)mBinaryBlob.getBytes();
|
sFacHeader* hdr = (sFacHeader*)mBinaryBlob.getBytes();
|
||||||
|
@ -57,8 +57,13 @@ void FacHeader::exportBinary()
|
||||||
hdr->save_data_owner_ids().set_end(mSaveDataOwnerIdPos.offset + mSaveDataOwnerIdPos.size);
|
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));
|
mBinaryBlob.alloc(sizeof(sFacHeader));
|
||||||
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
||||||
sFacHeader* hdr = (sFacHeader*)mBinaryBlob.getBytes();
|
sFacHeader* hdr = (sFacHeader*)mBinaryBlob.getBytes();
|
||||||
|
@ -70,66 +75,64 @@ void FacHeader::importBinary(const u8 * bytes)
|
||||||
|
|
||||||
mFsaRights = hdr->fac_flags();
|
mFsaRights = hdr->fac_flags();
|
||||||
mContentOwnerIdPos.offset = hdr->content_owner_ids().start();
|
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.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))
|
clearVariables();
|
||||||
{
|
|
||||||
throw fnd::Exception(kModuleName, "FAC header too small");
|
|
||||||
}
|
|
||||||
importBinary(bytes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
return mFsaRights;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FacHeader::setFsaRights(u64 flag)
|
void nx::FacHeader::setFsaRights(u64 flag)
|
||||||
{
|
{
|
||||||
mFsaRights = flag;
|
mFsaRights = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FacHeader::getContentOwnerIdOffset() const
|
size_t nx::FacHeader::getContentOwnerIdOffset() const
|
||||||
{
|
{
|
||||||
return mContentOwnerIdPos.offset;
|
return mContentOwnerIdPos.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FacHeader::getContentOwnerIdSize() const
|
size_t nx::FacHeader::getContentOwnerIdSize() const
|
||||||
{
|
{
|
||||||
return mContentOwnerIdPos.size;
|
return mContentOwnerIdPos.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FacHeader::setContentOwnerIdSize(size_t size)
|
void nx::FacHeader::setContentOwnerIdSize(size_t size)
|
||||||
{
|
{
|
||||||
mContentOwnerIdPos.size = size;
|
mContentOwnerIdPos.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FacHeader::getSaveDataOwnerIdOffset() const
|
size_t nx::FacHeader::getSaveDataOwnerIdOffset() const
|
||||||
{
|
{
|
||||||
return mSaveDataOwnerIdPos.offset;
|
return mSaveDataOwnerIdPos.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FacHeader::getSaveDataOwnerIdSize() const
|
size_t nx::FacHeader::getSaveDataOwnerIdSize() const
|
||||||
{
|
{
|
||||||
return mSaveDataOwnerIdPos.size;
|
return mSaveDataOwnerIdPos.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FacHeader::setSaveDataOwnerIdSize(size_t size)
|
void nx::FacHeader::setSaveDataOwnerIdSize(size_t size)
|
||||||
{
|
{
|
||||||
mSaveDataOwnerIdPos.size = size;
|
mSaveDataOwnerIdPos.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FacHeader::clearVariables()
|
void nx::FacHeader::clearVariables()
|
||||||
{
|
{
|
||||||
mFsaRights = 0;
|
mFsaRights = 0;
|
||||||
mContentOwnerIdPos.offset = 0;
|
mContentOwnerIdPos.offset = 0;
|
||||||
|
@ -138,13 +141,13 @@ void FacHeader::clearVariables()
|
||||||
mSaveDataOwnerIdPos.size = 0;
|
mSaveDataOwnerIdPos.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FacHeader::calculateOffsets()
|
void nx::FacHeader::calculateOffsets()
|
||||||
{
|
{
|
||||||
mContentOwnerIdPos.offset = align(sizeof(sFacHeader), 4);
|
mContentOwnerIdPos.offset = align(sizeof(sFacHeader), 4);
|
||||||
mSaveDataOwnerIdPos.offset = mContentOwnerIdPos.offset + align(mContentOwnerIdPos.size, 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) \
|
return (mFsaRights == other.mFsaRights) \
|
||||||
&& (mContentOwnerIdPos.offset == other.mContentOwnerIdPos.offset) \
|
&& (mContentOwnerIdPos.offset == other.mContentOwnerIdPos.offset) \
|
||||||
|
@ -153,7 +156,7 @@ bool FacHeader::isEqual(const FacHeader & other) const
|
||||||
&& (mSaveDataOwnerIdPos.size == other.mSaveDataOwnerIdPos.size);
|
&& (mSaveDataOwnerIdPos.size == other.mSaveDataOwnerIdPos.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FacHeader::copyFrom(const FacHeader & other)
|
void nx::FacHeader::copyFrom(const FacHeader & other)
|
||||||
{
|
{
|
||||||
if (other.getSize())
|
if (other.getSize())
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace nx
|
||||||
public:
|
public:
|
||||||
FacHeader();
|
FacHeader();
|
||||||
FacHeader(const FacHeader& other);
|
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;
|
||||||
bool operator!=(const FacHeader& other) const;
|
bool operator!=(const FacHeader& other) const;
|
||||||
|
@ -23,11 +23,11 @@ namespace nx
|
||||||
|
|
||||||
// export/import binary
|
// export/import binary
|
||||||
void exportBinary();
|
void exportBinary();
|
||||||
void importBinary(const u8* bytes);
|
|
||||||
void importBinary(const u8* bytes, size_t len);
|
void importBinary(const u8* bytes, size_t len);
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
u64 getFacSize() const;
|
void clear();
|
||||||
|
size_t getFacSize() const;
|
||||||
|
|
||||||
u64 getFsaRights() const;
|
u64 getFsaRights() const;
|
||||||
void setFsaRights(u64 flag);
|
void setFsaRights(u64 flag);
|
||||||
|
|
|
@ -13,8 +13,9 @@ namespace nx
|
||||||
virtual size_t getSize() const = 0;
|
virtual size_t getSize() const = 0;
|
||||||
|
|
||||||
virtual void exportBinary() = 0;
|
virtual void exportBinary() = 0;
|
||||||
virtual void importBinary(const u8* bytes) = 0;
|
|
||||||
virtual void importBinary(const u8* bytes, size_t len) = 0;
|
virtual void importBinary(const u8* bytes, size_t len) = 0;
|
||||||
|
|
||||||
|
virtual void clear() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,9 @@ void nx::InteruptHandler::operator=(const InteruptHandler & other)
|
||||||
|
|
||||||
void nx::InteruptHandler::importKernelCapabilityList(const fnd::List<KernelCapability>& caps)
|
void nx::InteruptHandler::importKernelCapabilityList(const fnd::List<KernelCapability>& caps)
|
||||||
{
|
{
|
||||||
|
if (caps.getSize() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
// convert to interupts
|
// convert to interupts
|
||||||
fnd::List<InteruptEntry> interupts;
|
fnd::List<InteruptEntry> interupts;
|
||||||
for (size_t i = 0; i < caps.getSize(); i++)
|
for (size_t i = 0; i < caps.getSize(); i++)
|
||||||
|
@ -92,12 +95,12 @@ bool nx::InteruptHandler::isSet() const
|
||||||
return mIsSet;
|
return mIsSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fnd::List<u16>& nx::InteruptHandler::getInterupts() const
|
const fnd::List<u16>& nx::InteruptHandler::getInteruptList() const
|
||||||
{
|
{
|
||||||
return mInterupts;
|
return mInterupts;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::InteruptHandler::setInterupts(const fnd::List<u16>& interupts)
|
void nx::InteruptHandler::setInteruptList(const fnd::List<u16>& interupts)
|
||||||
{
|
{
|
||||||
mInterupts.clear();
|
mInterupts.clear();
|
||||||
for (size_t i = 0; i < interupts.getSize(); i++)
|
for (size_t i = 0; i < interupts.getSize(); i++)
|
||||||
|
|
|
@ -21,8 +21,8 @@ namespace nx
|
||||||
bool isSet() const;
|
bool isSet() const;
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
const fnd::List<u16>& getInterupts() const;
|
const fnd::List<u16>& getInteruptList() const;
|
||||||
void setInterupts(const fnd::List<u16>& interupts);
|
void setInteruptList(const fnd::List<u16>& interupts);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string kModuleName = "INTERUPT_HANDLER";
|
const std::string kModuleName = "INTERUPT_HANDLER";
|
||||||
|
|
|
@ -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)
|
void nx::KcBinary::importBinary(const u8 * bytes, size_t len)
|
||||||
{
|
{
|
||||||
if ((len % sizeof(u32)) != 0)
|
if ((len % sizeof(u32)) != 0)
|
||||||
|
@ -134,6 +129,11 @@ void nx::KcBinary::importBinary(const u8 * bytes, size_t len)
|
||||||
mMiscFlags.importKernelCapabilityList(miscFlagsCaps);
|
mMiscFlags.importKernelCapabilityList(miscFlagsCaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nx::KcBinary::clear()
|
||||||
|
{
|
||||||
|
clearVariables();
|
||||||
|
}
|
||||||
|
|
||||||
const nx::ThreadInfoHandler & nx::KcBinary::getThreadInfo() const
|
const nx::ThreadInfoHandler & nx::KcBinary::getThreadInfo() const
|
||||||
{
|
{
|
||||||
return mThreadInfo;
|
return mThreadInfo;
|
||||||
|
|
|
@ -33,10 +33,10 @@ namespace nx
|
||||||
|
|
||||||
// export/import binary
|
// export/import binary
|
||||||
void exportBinary();
|
void exportBinary();
|
||||||
void importBinary(const u8* bytes);
|
|
||||||
void importBinary(const u8* bytes, size_t len);
|
void importBinary(const u8* bytes, size_t len);
|
||||||
|
|
||||||
// variables (consider further abstraction?)
|
// variables (consider further abstraction?)
|
||||||
|
void clear();
|
||||||
const ThreadInfoHandler& getThreadInfo() const;
|
const ThreadInfoHandler& getThreadInfo() const;
|
||||||
ThreadInfoHandler& getThreadInfo();
|
ThreadInfoHandler& getThreadInfo();
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,11 @@ void nx::MemoryMappingHandler::operator=(const MemoryMappingHandler & other)
|
||||||
|
|
||||||
void nx::MemoryMappingHandler::importKernelCapabilityList(const fnd::List<KernelCapability>& caps)
|
void nx::MemoryMappingHandler::importKernelCapabilityList(const fnd::List<KernelCapability>& caps)
|
||||||
{
|
{
|
||||||
fnd::List<MemoryPageEntry> entries;
|
if (caps.getSize() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// get entry list
|
||||||
|
fnd::List<MemoryPageEntry> entries;
|
||||||
for (size_t i = 0; i < caps.getSize(); i++)
|
for (size_t i = 0; i < caps.getSize(); i++)
|
||||||
{
|
{
|
||||||
entries[i].setKernelCapability(caps[i]);
|
entries[i].setKernelCapability(caps[i]);
|
||||||
|
@ -32,7 +35,7 @@ void nx::MemoryMappingHandler::importKernelCapabilityList(const fnd::List<Kernel
|
||||||
|
|
||||||
mMemRange.clear();
|
mMemRange.clear();
|
||||||
mMemPage.clear();
|
mMemPage.clear();
|
||||||
for (size_t i = 0; i < entries.getSize();)
|
for (size_t i = 0; i < entries.getSize(); i++)
|
||||||
{
|
{
|
||||||
// has flag means "MemMap"
|
// has flag means "MemMap"
|
||||||
if (entries[i].isMultiplePages())
|
if (entries[i].isMultiplePages())
|
||||||
|
|
|
@ -6,6 +6,21 @@ nx::MiscFlagsHandler::MiscFlagsHandler() :
|
||||||
mIsSet(false)
|
mIsSet(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
bool nx::MiscFlagsHandler::operator==(const MiscFlagsHandler & other) const
|
||||||
|
{
|
||||||
|
return isEqual(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nx::MiscFlagsHandler::operator!=(const MiscFlagsHandler & other) const
|
||||||
|
{
|
||||||
|
return !isEqual(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::MiscFlagsHandler::operator=(const MiscFlagsHandler & other)
|
||||||
|
{
|
||||||
|
copyFrom(other);
|
||||||
|
}
|
||||||
|
|
||||||
void nx::MiscFlagsHandler::importKernelCapabilityList(const fnd::List<KernelCapability>& caps)
|
void nx::MiscFlagsHandler::importKernelCapabilityList(const fnd::List<KernelCapability>& caps)
|
||||||
{
|
{
|
||||||
if (caps.getSize() > kMaxKernelCapNum)
|
if (caps.getSize() > kMaxKernelCapNum)
|
||||||
|
@ -16,8 +31,18 @@ void nx::MiscFlagsHandler::importKernelCapabilityList(const fnd::List<KernelCapa
|
||||||
if (caps.getSize() == 0)
|
if (caps.getSize() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mEntry.setKernelCapability(caps[0]);
|
MiscFlagsEntry entry;
|
||||||
|
entry.setKernelCapability(caps[0]);
|
||||||
|
|
||||||
|
clear();
|
||||||
|
for (u32 i = 0; i < FLAG_NUM; i++)
|
||||||
|
{
|
||||||
|
if ((entry.getFlags() & BIT(i)) == BIT(i))
|
||||||
|
{
|
||||||
|
mFlags.addElement((Flags)i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mIsSet = true;
|
mIsSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,13 +51,25 @@ void nx::MiscFlagsHandler::exportKernelCapabilityList(fnd::List<KernelCapability
|
||||||
if (isSet() == false)
|
if (isSet() == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
caps.addElement(mEntry.getKernelCapability());
|
// convert list to word flags
|
||||||
|
u32 flag;
|
||||||
|
for (size_t i = 0; i < mFlags.getSize(); i++)
|
||||||
|
{
|
||||||
|
flag |= BIT(mFlags[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create MiscFlag entry
|
||||||
|
MiscFlagsEntry entry;
|
||||||
|
entry.setFlags(flag);
|
||||||
|
|
||||||
|
// add to list
|
||||||
|
caps.addElement(entry.getKernelCapability());
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::MiscFlagsHandler::clear()
|
void nx::MiscFlagsHandler::clear()
|
||||||
{
|
{
|
||||||
mIsSet = false;
|
mIsSet = false;
|
||||||
mEntry.setFlags(0);
|
mFlags.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nx::MiscFlagsHandler::isSet() const
|
bool nx::MiscFlagsHandler::isSet() const
|
||||||
|
@ -40,25 +77,25 @@ bool nx::MiscFlagsHandler::isSet() const
|
||||||
return mIsSet;
|
return mIsSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 nx::MiscFlagsHandler::getFlags() const
|
const fnd::List<nx::MiscFlagsHandler::Flags>& nx::MiscFlagsHandler::getFlagList() const
|
||||||
{
|
{
|
||||||
return mEntry.getFlags();
|
return mFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::MiscFlagsHandler::setFlags(u32 flags)
|
void nx::MiscFlagsHandler::setFlagList(fnd::List<Flags> flags)
|
||||||
{
|
{
|
||||||
mEntry.setFlags(flags);
|
mFlags = flags;
|
||||||
mIsSet = true;
|
mIsSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::MiscFlagsHandler::copyFrom(const MiscFlagsHandler & other)
|
void nx::MiscFlagsHandler::copyFrom(const MiscFlagsHandler & other)
|
||||||
{
|
{
|
||||||
mIsSet = other.mIsSet;
|
mIsSet = other.mIsSet;
|
||||||
mEntry.setKernelCapability(other.mEntry.getKernelCapability());
|
mFlags = other.mFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nx::MiscFlagsHandler::isEqual(const MiscFlagsHandler & other) const
|
bool nx::MiscFlagsHandler::isEqual(const MiscFlagsHandler & other) const
|
||||||
{
|
{
|
||||||
return (mIsSet == other.mIsSet) \
|
return (mIsSet == other.mIsSet) \
|
||||||
&& (mEntry.getKernelCapability() == other.mEntry.getKernelCapability());
|
&& (mFlags == other.mFlags);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,21 +10,22 @@ namespace nx
|
||||||
public:
|
public:
|
||||||
enum Flags
|
enum Flags
|
||||||
{
|
{
|
||||||
FLAG_ENABLE_DEBUG = BIT(0),
|
FLAG_ENABLE_DEBUG,
|
||||||
FLAG_FORCE_DEBUG = BIT(1),
|
FLAG_FORCE_DEBUG,
|
||||||
FLAG_UNK02 = BIT(2),
|
FLAG_UNK02,
|
||||||
FLAG_UNK03 = BIT(3),
|
FLAG_UNK03,
|
||||||
FLAG_UNK04 = BIT(4),
|
FLAG_UNK04,
|
||||||
FLAG_UNK05 = BIT(5),
|
FLAG_UNK05,
|
||||||
FLAG_UNK06 = BIT(6),
|
FLAG_UNK06,
|
||||||
FLAG_UNK07 = BIT(7),
|
FLAG_UNK07,
|
||||||
FLAG_UNK08 = BIT(8),
|
FLAG_UNK08,
|
||||||
FLAG_UNK09 = BIT(9),
|
FLAG_UNK09,
|
||||||
FLAG_UNK10 = BIT(10),
|
FLAG_UNK10,
|
||||||
FLAG_UNK11 = BIT(11),
|
FLAG_UNK11,
|
||||||
FLAG_UNK12 = BIT(12),
|
FLAG_UNK12,
|
||||||
FLAG_UNK13 = BIT(13),
|
FLAG_UNK13,
|
||||||
FLAG_UNK14 = BIT(14),
|
FLAG_UNK14,
|
||||||
|
FLAG_NUM
|
||||||
};
|
};
|
||||||
|
|
||||||
MiscFlagsHandler();
|
MiscFlagsHandler();
|
||||||
|
@ -40,14 +41,15 @@ namespace nx
|
||||||
bool isSet() const;
|
bool isSet() const;
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
u32 getFlags() const;
|
const fnd::List<Flags>& getFlagList() const;
|
||||||
void setFlags(u32 flags);
|
void setFlagList(fnd::List<Flags> flags);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string kModuleName = "MISC_FLAGS_HANDLER";
|
const std::string kModuleName = "MISC_FLAGS_HANDLER";
|
||||||
static const size_t kMaxKernelCapNum = 1;
|
static const size_t kMaxKernelCapNum = 1;
|
||||||
|
|
||||||
bool mIsSet;
|
bool mIsSet;
|
||||||
MiscFlagsEntry mEntry;
|
fnd::List<Flags> mFlags;
|
||||||
|
|
||||||
void copyFrom(const MiscFlagsHandler& other);
|
void copyFrom(const MiscFlagsHandler& other);
|
||||||
bool isEqual(const MiscFlagsHandler& other) const;
|
bool isEqual(const MiscFlagsHandler& other) const;
|
||||||
|
|
|
@ -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();
|
clearVariables();
|
||||||
|
|
||||||
mBinaryBlob.alloc(sizeof(sNcaHeader));
|
mBinaryBlob.alloc(sizeof(sNcaHeader));
|
||||||
memcpy(mBinaryBlob.getBytes(), bytes, 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");
|
throw fnd::Exception(kModuleName, "NCA header corrupt");
|
||||||
}
|
}
|
||||||
|
|
||||||
mBlockSize = hdr->block_size();
|
mBlockSize = hdr->block_size();
|
||||||
mNcaSize = hdr->nca_size();
|
mNcaSize = hdr->nca_size();
|
||||||
mProgramId = hdr->program_id();
|
mProgramId = hdr->program_id();
|
||||||
|
@ -57,10 +62,10 @@ void NcaHeader::importBinary(const u8 * bytes)
|
||||||
{
|
{
|
||||||
// determine section index
|
// determine section index
|
||||||
u8 section = kSectionNum - 1 - i;
|
u8 section = kSectionNum - 1 - i;
|
||||||
|
|
||||||
// skip sections that don't exist
|
// skip sections that don't exist
|
||||||
if (hdr->section(section).start() == 0 && hdr->section(section).end() == 0) continue;
|
if (hdr->section(section).start() == 0 && hdr->section(section).end() == 0) continue;
|
||||||
|
|
||||||
// add high level struct
|
// 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) });
|
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))
|
clearVariables();
|
||||||
{
|
|
||||||
throw fnd::Exception(kModuleName, "NCA header size is too small");
|
|
||||||
}
|
|
||||||
importBinary(bytes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 NcaHeader::getNcaSize() const
|
u64 NcaHeader::getNcaSize() const
|
||||||
|
@ -192,9 +193,9 @@ NcaHeader::NcaHeader(const NcaHeader & other)
|
||||||
copyFrom(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
|
bool NcaHeader::operator==(const NcaHeader & other) const
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace nx
|
||||||
|
|
||||||
NcaHeader();
|
NcaHeader();
|
||||||
NcaHeader(const NcaHeader& other);
|
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;
|
||||||
bool operator!=(const NcaHeader& other) const;
|
bool operator!=(const NcaHeader& other) const;
|
||||||
|
@ -59,10 +59,10 @@ namespace nx
|
||||||
|
|
||||||
// export/import binary
|
// export/import binary
|
||||||
void exportBinary();
|
void exportBinary();
|
||||||
void importBinary(const u8* bytes);
|
|
||||||
void importBinary(const u8* bytes, size_t len);
|
void importBinary(const u8* bytes, size_t len);
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
|
void clear();
|
||||||
u64 getNcaSize() const;
|
u64 getNcaSize() const;
|
||||||
void setNcaSize(u64 size);
|
void setNcaSize(u64 size);
|
||||||
u64 getProgramId() const;
|
u64 getProgramId() const;
|
||||||
|
|
|
@ -12,9 +12,9 @@ nx::NpdmHeader::NpdmHeader(const NpdmHeader & other)
|
||||||
copyFrom(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
|
bool nx::NpdmHeader::operator==(const NpdmHeader & other) const
|
||||||
|
@ -122,8 +122,15 @@ void nx::NpdmHeader::exportBinary()
|
||||||
hdr->acid().set_size(mAcidPos.size);
|
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));
|
mBinaryBlob.alloc(sizeof(sNpdmHeader));
|
||||||
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
||||||
sNpdmHeader* hdr = (sNpdmHeader*)mBinaryBlob.getBytes();
|
sNpdmHeader* hdr = (sNpdmHeader*)mBinaryBlob.getBytes();
|
||||||
|
@ -148,13 +155,9 @@ void nx::NpdmHeader::importBinary(const u8 * bytes)
|
||||||
mAcidPos.size = hdr->acid().size();
|
mAcidPos.size = hdr->acid().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::NpdmHeader::importBinary(const u8 * bytes, size_t len)
|
void nx::NpdmHeader::clear()
|
||||||
{
|
{
|
||||||
if (len < sizeof(sNpdmHeader))
|
clearVariables();
|
||||||
{
|
|
||||||
throw fnd::Exception(kModuleName, "NPDM header too small");
|
|
||||||
}
|
|
||||||
importBinary(bytes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nx::NpdmHeader::getNpdmSize() const
|
size_t nx::NpdmHeader::getNpdmSize() const
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace nx
|
||||||
|
|
||||||
NpdmHeader();
|
NpdmHeader();
|
||||||
NpdmHeader(const NpdmHeader& other);
|
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;
|
||||||
bool operator!=(const NpdmHeader& other) const;
|
bool operator!=(const NpdmHeader& other) const;
|
||||||
|
@ -61,10 +61,10 @@ namespace nx
|
||||||
|
|
||||||
// export/import binary
|
// export/import binary
|
||||||
void exportBinary();
|
void exportBinary();
|
||||||
void importBinary(const u8* bytes);
|
|
||||||
void importBinary(const u8* bytes, size_t len);
|
void importBinary(const u8* bytes, size_t len);
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
|
void clear();
|
||||||
size_t getNpdmSize() const;
|
size_t getNpdmSize() const;
|
||||||
|
|
||||||
InstructionType getInstructionType() const;
|
InstructionType getInstructionType() const;
|
||||||
|
|
|
@ -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)
|
void SacBinary::importBinary(const u8 * bytes, size_t len)
|
||||||
{
|
{
|
||||||
clearVariables();
|
clearVariables();
|
||||||
|
@ -76,6 +71,11 @@ void SacBinary::importBinary(const u8 * bytes, size_t len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nx::SacBinary::clear()
|
||||||
|
{
|
||||||
|
clearVariables();
|
||||||
|
}
|
||||||
|
|
||||||
const fnd::List<SacEntry>& SacBinary::getServiceList() const
|
const fnd::List<SacEntry>& SacBinary::getServiceList() const
|
||||||
{
|
{
|
||||||
return mServices;
|
return mServices;
|
||||||
|
|
|
@ -26,10 +26,10 @@ namespace nx
|
||||||
|
|
||||||
// export/import binary
|
// export/import binary
|
||||||
void exportBinary();
|
void exportBinary();
|
||||||
void importBinary(const u8* bytes);
|
|
||||||
void importBinary(const u8* bytes, size_t len);
|
void importBinary(const u8* bytes, size_t len);
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
|
void clear();
|
||||||
const fnd::List<SacEntry>& getServiceList() const;
|
const fnd::List<SacEntry>& getServiceList() const;
|
||||||
void addService(const SacEntry& service);
|
void addService(const SacEntry& service);
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -55,25 +55,25 @@ void SacEntry::exportBinary()
|
||||||
throw fnd::Exception(kModuleName, "Failed to allocate memory for SacEntry: " + std::string(e.what()));
|
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)
|
if (mName.length() > kMaxServiceNameLen)
|
||||||
{
|
{
|
||||||
throw fnd::Exception(kModuleName, "Service name string too long (max 8 chars)");
|
throw fnd::Exception(kModuleName, "Service name string too long (max 8 chars)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy data into binary blob
|
// 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());
|
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)
|
void SacEntry::importBinary(const u8 * bytes, size_t len)
|
||||||
{
|
{
|
||||||
bool isServer = (bytes[0] & SAC_IS_SERVER) == SAC_IS_SERVER;
|
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)
|
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);
|
mName = std::string((const char*)(mBinaryBlob.getBytes() + 1), nameLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nx::SacEntry::clear()
|
||||||
|
{
|
||||||
|
mIsServer = false;
|
||||||
|
mName.clear();
|
||||||
|
}
|
||||||
|
|
||||||
bool SacEntry::isServer() const
|
bool SacEntry::isServer() const
|
||||||
{
|
{
|
||||||
return mIsServer;
|
return mIsServer;
|
||||||
|
|
|
@ -23,10 +23,10 @@ namespace nx
|
||||||
|
|
||||||
// export/import binary
|
// export/import binary
|
||||||
void exportBinary();
|
void exportBinary();
|
||||||
void importBinary(const u8* bytes);
|
|
||||||
void importBinary(const u8* bytes, size_t len);
|
void importBinary(const u8* bytes, size_t len);
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
|
void clear();
|
||||||
bool isServer() const;
|
bool isServer() const;
|
||||||
void setIsServer(bool isServer);
|
void setIsServer(bool isServer);
|
||||||
const std::string& getName() const;
|
const std::string& getName() const;
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace nx
|
||||||
const std::string kModuleName = "SYSTEM_CALL_ENTRY";
|
const std::string kModuleName = "SYSTEM_CALL_ENTRY";
|
||||||
static const KernelCapability::KernelCapId kCapId = KernelCapability::KC_ENABLE_SYSTEM_CALLS;
|
static const KernelCapability::KernelCapId kCapId = KernelCapability::KC_ENABLE_SYSTEM_CALLS;
|
||||||
static const u32 kSysCallUpperBits = 3;
|
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 kSysCallUpperMax = BIT(kSysCallUpperBits) - 1;
|
||||||
static const u32 kSysCallLowerMax = BIT(kSysCallLowerBits) - 1;
|
static const u32 kSysCallLowerMax = BIT(kSysCallLowerBits) - 1;
|
||||||
|
|
||||||
|
|
|
@ -24,18 +24,19 @@ void nx::SystemCallHandler::operator=(const SystemCallHandler & other)
|
||||||
|
|
||||||
void nx::SystemCallHandler::importKernelCapabilityList(const fnd::List<KernelCapability>& caps)
|
void nx::SystemCallHandler::importKernelCapabilityList(const fnd::List<KernelCapability>& caps)
|
||||||
{
|
{
|
||||||
|
if (caps.getSize() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
SystemCallEntry entry;
|
SystemCallEntry entry;
|
||||||
|
|
||||||
u8 syscallUpper, syscall;
|
u8 syscallUpper, syscall;
|
||||||
for (size_t i = 0; i < caps.getSize(); i++)
|
for (size_t i = 0; i < caps.getSize(); i++)
|
||||||
{
|
{
|
||||||
entry.setKernelCapability(caps[i]);
|
entry.setKernelCapability(caps[i]);
|
||||||
|
|
||||||
syscallUpper = 24 * entry.getSystemCallUpperBits();
|
syscallUpper = 24 * entry.getSystemCallUpperBits();
|
||||||
for (u8 j = 0; j < 24; j++)
|
for (u8 j = 0; j < 24; j++)
|
||||||
{
|
{
|
||||||
syscall = syscallUpper + j;
|
syscall = syscallUpper + j;
|
||||||
|
|
||||||
if (((entry.getSystemCallLowerBits() >> j) & 1) == 1)
|
if (((entry.getSystemCallLowerBits() >> j) & 1) == 1)
|
||||||
{
|
{
|
||||||
mSystemCalls.hasElement(syscall) == false ? mSystemCalls.addElement(syscall) : throw fnd::Exception(kModuleName, "SystemCall already added");
|
mSystemCalls.hasElement(syscall) == false ? mSystemCalls.addElement(syscall) : throw fnd::Exception(kModuleName, "SystemCall already added");
|
||||||
|
@ -94,7 +95,7 @@ const fnd::List<u8>& nx::SystemCallHandler::getSystemCalls() const
|
||||||
return mSystemCalls;
|
return mSystemCalls;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::SystemCallHandler::setSystemCalls(const fnd::List<u8>& calls)
|
void nx::SystemCallHandler::setSystemCallList(const fnd::List<u8>& calls)
|
||||||
{
|
{
|
||||||
mSystemCalls.clear();
|
mSystemCalls.clear();
|
||||||
for (size_t i = 0; i < calls.getSize(); i++)
|
for (size_t i = 0; i < calls.getSize(); i++)
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace nx
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
const fnd::List<u8>& getSystemCalls() const;
|
const fnd::List<u8>& getSystemCalls() const;
|
||||||
void setSystemCalls(const fnd::List<u8>& calls);
|
void setSystemCallList(const fnd::List<u8>& calls);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string kModuleName = "SYSTEM_CALL_HANDLER";
|
const std::string kModuleName = "SYSTEM_CALL_HANDLER";
|
||||||
|
|
|
@ -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]);
|
decryptNcaSectorXts(nca, sector, 1, crypto::aes::nx::nca_header_key[0], crypto::aes::nx::nca_header_key[1]);
|
||||||
|
|
||||||
nx::NcaHeader hdr;
|
nx::NcaHeader hdr;
|
||||||
hdr.importBinary(sector);
|
hdr.importBinary(sector, kNcaSectorSize);
|
||||||
|
|
||||||
printf("[NCA Header]\n");
|
printf("[NCA Header]\n");
|
||||||
printf(" Size: 0x%" PRIx64 "\n", hdr.getNcaSize());
|
printf(" Size: 0x%" PRIx64 "\n", hdr.getNcaSize());
|
||||||
|
|
Loading…
Reference in a new issue