mirror of
https://github.com/jakcron/nstool
synced 2024-11-15 02:06:40 +00:00
[nx] Implemented NpdmBinary and associated child classes.
This commit is contained in:
parent
7dd27fd5c8
commit
99151507c6
24 changed files with 768 additions and 354 deletions
|
@ -3,7 +3,9 @@
|
||||||
|
|
||||||
|
|
||||||
nx::AciBinary::AciBinary()
|
nx::AciBinary::AciBinary()
|
||||||
{}
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
nx::AciBinary::AciBinary(const AciBinary & other)
|
nx::AciBinary::AciBinary(const AciBinary & other)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,28 +2,17 @@
|
||||||
|
|
||||||
using namespace nx;
|
using namespace nx;
|
||||||
|
|
||||||
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()
|
void AciHeader::calculateSectionOffsets()
|
||||||
{
|
{
|
||||||
mFac.offset = align(sizeof(sAciHeader), kAciAlignSize);
|
mFac.offset = align(mHeaderOffset, kAciAlignSize) + align(sizeof(sAciHeader), kAciAlignSize);
|
||||||
mSac.offset = mFac.offset + align(mFac.size, kAciAlignSize);
|
mSac.offset = mFac.offset + align(mFac.size, kAciAlignSize);
|
||||||
mKc.offset = mSac.offset + align(mSac.size, kAciAlignSize);
|
mKc.offset = mSac.offset + align(mSac.size, kAciAlignSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AciHeader::isEqual(const AciHeader & other) const
|
bool AciHeader::isEqual(const AciHeader & other) const
|
||||||
{
|
{
|
||||||
return (mType == other.mType) \
|
return (mHeaderOffset == other.mHeaderOffset) \
|
||||||
|
&& (mType == other.mType) \
|
||||||
&& (mAcidSize == other.mAcidSize) \
|
&& (mAcidSize == other.mAcidSize) \
|
||||||
&& (mProgramId == other.mProgramId) \
|
&& (mProgramId == other.mProgramId) \
|
||||||
&& (mFac == other.mFac) \
|
&& (mFac == other.mFac) \
|
||||||
|
@ -39,6 +28,7 @@ void AciHeader::copyFrom(const AciHeader & other)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
mHeaderOffset = other.mHeaderOffset;
|
||||||
mType = other.mType;
|
mType = other.mType;
|
||||||
mAcidSize = other.mAcidSize;
|
mAcidSize = other.mAcidSize;
|
||||||
mProgramId = other.mProgramId;
|
mProgramId = other.mProgramId;
|
||||||
|
@ -50,7 +40,7 @@ void AciHeader::copyFrom(const AciHeader & other)
|
||||||
|
|
||||||
AciHeader::AciHeader()
|
AciHeader::AciHeader()
|
||||||
{
|
{
|
||||||
clearVariables();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
AciHeader::AciHeader(const AciHeader & other)
|
AciHeader::AciHeader(const AciHeader & other)
|
||||||
|
@ -106,17 +96,36 @@ void AciHeader::exportBinary()
|
||||||
throw fnd::Exception(kModuleName, "Unexpected ACI type");
|
throw fnd::Exception(kModuleName, "Unexpected ACI type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
hdr->set_version(mFormatVersion);
|
||||||
|
|
||||||
if (mType == TYPE_ACI0)
|
if (mType == TYPE_ACI0)
|
||||||
{
|
{
|
||||||
// set program
|
// set program
|
||||||
hdr->set_program_id(mProgramId);
|
hdr->set_program_id(mProgramId);
|
||||||
|
switch (mFormatVersion)
|
||||||
|
{
|
||||||
|
case(0):
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw fnd::Exception(kModuleName, "Unsupported ACI0 version");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (mType == TYPE_ACID)
|
else if (mType == TYPE_ACID)
|
||||||
{
|
{
|
||||||
hdr->set_version(mAcidVersion);
|
|
||||||
switch (mAcidVersion)
|
switch (mFormatVersion)
|
||||||
{
|
{
|
||||||
case(0):
|
case(0):
|
||||||
|
mAcidSize = getAciSize();
|
||||||
hdr->set_size(mAcidSize);
|
hdr->set_size(mAcidSize);
|
||||||
hdr->set_program_id_min(0);
|
hdr->set_program_id_min(0);
|
||||||
hdr->set_program_id_max(0);
|
hdr->set_program_id_max(0);
|
||||||
|
@ -130,16 +139,6 @@ void AciHeader::exportBinary()
|
||||||
throw fnd::Exception(kModuleName, "Unsupported ACID version");
|
throw fnd::Exception(kModuleName, "Unsupported ACID version");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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, size_t len)
|
void AciHeader::importBinary(const u8 * bytes, size_t len)
|
||||||
|
@ -149,7 +148,7 @@ void AciHeader::importBinary(const u8 * bytes, size_t len)
|
||||||
throw fnd::Exception(kModuleName, "ACI header too small");
|
throw fnd::Exception(kModuleName, "ACI header too small");
|
||||||
}
|
}
|
||||||
|
|
||||||
clearVariables();
|
clear();
|
||||||
|
|
||||||
mBinaryBlob.alloc(sizeof(sAciHeader));
|
mBinaryBlob.alloc(sizeof(sAciHeader));
|
||||||
memcpy(mBinaryBlob.getBytes(), bytes, sizeof(sAciHeader));
|
memcpy(mBinaryBlob.getBytes(), bytes, sizeof(sAciHeader));
|
||||||
|
@ -173,16 +172,24 @@ void AciHeader::importBinary(const u8 * bytes, size_t len)
|
||||||
if (mType == TYPE_ACI0)
|
if (mType == TYPE_ACI0)
|
||||||
{
|
{
|
||||||
mProgramId = hdr->program_id();
|
mProgramId = hdr->program_id();
|
||||||
mAcidVersion = 0;
|
mFormatVersion = hdr->version();
|
||||||
mAcidSize = 0;
|
mAcidSize = 0;
|
||||||
mProgramIdMin = 0;
|
mProgramIdMin = 0;
|
||||||
mProgramIdMax = 0;
|
mProgramIdMax = 0;
|
||||||
|
|
||||||
|
switch (mFormatVersion)
|
||||||
|
{
|
||||||
|
case(0):
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw fnd::Exception(kModuleName, "Unsupported ACI0 version");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (mType == TYPE_ACID)
|
else if (mType == TYPE_ACID)
|
||||||
{
|
{
|
||||||
mProgramId = 0;
|
mProgramId = 0;
|
||||||
mAcidVersion = hdr->version();
|
mFormatVersion = hdr->version();
|
||||||
switch (mAcidVersion)
|
switch (mFormatVersion)
|
||||||
{
|
{
|
||||||
case(0):
|
case(0):
|
||||||
mAcidSize = hdr->size();
|
mAcidSize = hdr->size();
|
||||||
|
@ -199,17 +206,28 @@ void AciHeader::importBinary(const u8 * bytes, size_t len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mFac.offset = hdr->fac().offset();
|
// the header offset is the MIN(sac.offset, fac.offset, kc.offset) - sizeof(sHeader)
|
||||||
|
mHeaderOffset = MAX(MIN(hdr->sac().offset(), MIN(hdr->fac().offset(), hdr->kc().offset())), align(sizeof(sAciHeader), kAciAlignSize)) - align(sizeof(sAciHeader), kAciAlignSize);
|
||||||
|
|
||||||
|
mFac.offset = hdr->fac().offset() - mHeaderOffset;
|
||||||
mFac.size = hdr->fac().size();
|
mFac.size = hdr->fac().size();
|
||||||
mSac.offset = hdr->sac().offset();
|
mSac.offset = hdr->sac().offset() - mHeaderOffset;
|
||||||
mSac.size = hdr->sac().size();
|
mSac.size = hdr->sac().size();
|
||||||
mKc.offset = hdr->kc().offset();
|
mKc.offset = hdr->kc().offset() - mHeaderOffset;
|
||||||
mKc.size = hdr->kc().size();
|
mKc.size = hdr->kc().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::AciHeader::clear()
|
void nx::AciHeader::clear()
|
||||||
{
|
{
|
||||||
clearVariables();
|
mHeaderOffset = 0;
|
||||||
|
mType = TYPE_ACI0;
|
||||||
|
mProgramId = 0;
|
||||||
|
mFac.offset = 0;
|
||||||
|
mFac.size = 0;
|
||||||
|
mSac.offset = 0;
|
||||||
|
mSac.size = 0;
|
||||||
|
mKc.offset = 0;
|
||||||
|
mKc.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nx::AciHeader::getAciSize() const
|
size_t nx::AciHeader::getAciSize() const
|
||||||
|
@ -217,14 +235,14 @@ size_t nx::AciHeader::getAciSize() const
|
||||||
return MAX(MAX(MAX(mSac.offset + mSac.size, mKc.offset + mKc.size), mFac.offset + mFac.size), sizeof(sAciHeader));
|
return MAX(MAX(MAX(mSac.offset + mSac.size, mKc.offset + mKc.size), mFac.offset + mFac.size), sizeof(sAciHeader));
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 nx::AciHeader::getAcidVersion() const
|
u32 nx::AciHeader::getFormatVersion() const
|
||||||
{
|
{
|
||||||
return mAcidVersion;
|
return mFormatVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::AciHeader::setAcidVersion(u32 version)
|
void nx::AciHeader::setFormatVersion(u32 version)
|
||||||
{
|
{
|
||||||
mAcidVersion = version;
|
mFormatVersion = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nx::AciHeader::getAcidSize() const
|
size_t nx::AciHeader::getAcidSize() const
|
||||||
|
@ -232,10 +250,12 @@ size_t nx::AciHeader::getAcidSize() const
|
||||||
return mAcidSize;
|
return mAcidSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void nx::AciHeader::setAcidSize(size_t size)
|
void nx::AciHeader::setAcidSize(size_t size)
|
||||||
{
|
{
|
||||||
mAcidSize = size;
|
mAcidSize = size;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
u64 nx::AciHeader::getProgramIdMin() const
|
u64 nx::AciHeader::getProgramIdMin() const
|
||||||
{
|
{
|
||||||
|
@ -257,6 +277,11 @@ void nx::AciHeader::setProgramIdMax(u64 program_id)
|
||||||
mProgramIdMax = program_id;
|
mProgramIdMax = program_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nx::AciHeader::setHeaderOffset(size_t offset)
|
||||||
|
{
|
||||||
|
mHeaderOffset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
AciHeader::AciType AciHeader::getAciType() const
|
AciHeader::AciType AciHeader::getAciType() const
|
||||||
{
|
{
|
||||||
return mType;
|
return mType;
|
||||||
|
@ -282,7 +307,7 @@ const AciHeader::sSection & AciHeader::getFacPos() const
|
||||||
return mFac;
|
return mFac;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AciHeader::setFacSize(u32 size)
|
void AciHeader::setFacSize(size_t size)
|
||||||
{
|
{
|
||||||
mFac.size = size;
|
mFac.size = size;
|
||||||
}
|
}
|
||||||
|
@ -292,7 +317,7 @@ const AciHeader::sSection & AciHeader::getSacPos() const
|
||||||
return mSac;
|
return mSac;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AciHeader::setSacSize(u32 size)
|
void AciHeader::setSacSize(size_t size)
|
||||||
{
|
{
|
||||||
mSac.size = size;
|
mSac.size = size;
|
||||||
}
|
}
|
||||||
|
@ -302,7 +327,7 @@ const AciHeader::sSection & AciHeader::getKcPos() const
|
||||||
return mKc;
|
return mKc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AciHeader::setKcSize(u32 size)
|
void AciHeader::setKcSize(size_t size)
|
||||||
{
|
{
|
||||||
mKc.size = size;
|
mKc.size = size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,24 +63,25 @@ namespace nx
|
||||||
void setProgramId(u64 program_id);
|
void setProgramId(u64 program_id);
|
||||||
|
|
||||||
// ACID only
|
// ACID only
|
||||||
u32 getAcidVersion() const;
|
|
||||||
void setAcidVersion(u32 version);
|
|
||||||
size_t getAcidSize() const;
|
size_t getAcidSize() const;
|
||||||
void setAcidSize(size_t size);
|
//void setAcidSize(size_t size);
|
||||||
u64 getProgramIdMin() const;
|
u64 getProgramIdMin() const;
|
||||||
void setProgramIdMin(u64 program_id);
|
void setProgramIdMin(u64 program_id);
|
||||||
u64 getProgramIdMax() const;
|
u64 getProgramIdMax() const;
|
||||||
void setProgramIdMax(u64 program_id);
|
void setProgramIdMax(u64 program_id);
|
||||||
|
|
||||||
// ACID & ACI0
|
// ACID & ACI0
|
||||||
|
void setHeaderOffset(size_t offset);
|
||||||
AciType getAciType() const;
|
AciType getAciType() const;
|
||||||
void setAciType(AciType type);
|
void setAciType(AciType type);
|
||||||
|
u32 getFormatVersion() const;
|
||||||
|
void setFormatVersion(u32 version);
|
||||||
const sSection& getFacPos() const;
|
const sSection& getFacPos() const;
|
||||||
void setFacSize(u32 size);
|
void setFacSize(size_t size);
|
||||||
const sSection& getSacPos() const;
|
const sSection& getSacPos() const;
|
||||||
void setSacSize(u32 size);
|
void setSacSize(size_t size);
|
||||||
const sSection& getKcPos() const;
|
const sSection& getKcPos() const;
|
||||||
void setKcSize(u32 size);
|
void setKcSize(size_t size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string kModuleName = "ACI_HEADER";
|
const std::string kModuleName = "ACI_HEADER";
|
||||||
|
@ -94,8 +95,8 @@ 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_0[4];
|
||||||
u32 version_; // set in ACID only, v0 has size, but no pid range, v1 has no size by pid range
|
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)
|
||||||
u64 program_id_max_;
|
u64 program_id_max_;
|
||||||
struct sAciSection
|
struct sAciSection
|
||||||
|
@ -109,7 +110,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_, reserved_3;
|
} fac_, sac_, kc_;
|
||||||
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); }
|
||||||
|
@ -147,16 +148,15 @@ namespace nx
|
||||||
u64 mProgramId;
|
u64 mProgramId;
|
||||||
|
|
||||||
// ACID variables
|
// ACID variables
|
||||||
u32 mAcidVersion;
|
|
||||||
size_t mAcidSize;
|
size_t mAcidSize;
|
||||||
u64 mProgramIdMin;
|
u64 mProgramIdMin;
|
||||||
u64 mProgramIdMax;
|
u64 mProgramIdMax;
|
||||||
|
|
||||||
// ACI(D) variables
|
// ACI(D) variables
|
||||||
|
size_t mHeaderOffset;
|
||||||
AciType mType;
|
AciType mType;
|
||||||
|
u32 mFormatVersion;
|
||||||
sSection mFac, mSac, mKc;
|
sSection mFac, mSac, mKc;
|
||||||
|
|
||||||
void clearVariables();
|
|
||||||
void calculateSectionOffsets();
|
void calculateSectionOffsets();
|
||||||
bool isEqual(const AciHeader& other) const;
|
bool isEqual(const AciHeader& other) const;
|
||||||
void copyFrom(const AciHeader& other);
|
void copyFrom(const AciHeader& other);
|
||||||
|
|
142
lib/nx/AcidBinary.cpp
Normal file
142
lib/nx/AcidBinary.cpp
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
#include "AcidBinary.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
nx::AcidBinary::AcidBinary()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
nx::AcidBinary::AcidBinary(const AcidBinary & other)
|
||||||
|
{
|
||||||
|
copyFrom(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
nx::AcidBinary::AcidBinary(const u8 * bytes, size_t len)
|
||||||
|
{
|
||||||
|
importBinary(bytes, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::AcidBinary::clear()
|
||||||
|
{
|
||||||
|
AciBinary::clear();
|
||||||
|
mEmbeddedPublicKey = crypto::rsa::sRsa2048Key();
|
||||||
|
}
|
||||||
|
|
||||||
|
const crypto::rsa::sRsa2048Key & nx::AcidBinary::getPublicKey() const
|
||||||
|
{
|
||||||
|
return mEmbeddedPublicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::AcidBinary::setPublicKey(const crypto::rsa::sRsa2048Key & key)
|
||||||
|
{
|
||||||
|
mEmbeddedPublicKey = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nx::AcidBinary::isEqual(const AcidBinary & other) const
|
||||||
|
{
|
||||||
|
return AciBinary::operator==(other) \
|
||||||
|
&& (mEmbeddedPublicKey == other.mEmbeddedPublicKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::AcidBinary::copyFrom(const AcidBinary & other)
|
||||||
|
{
|
||||||
|
if (other.getSize())
|
||||||
|
{
|
||||||
|
importBinary(other.getBytes(), other.getSize());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AciBinary::operator=(other);
|
||||||
|
mEmbeddedPublicKey = other.mEmbeddedPublicKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nx::AcidBinary::operator==(const AcidBinary & other) const
|
||||||
|
{
|
||||||
|
return isEqual(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nx::AcidBinary::operator!=(const AcidBinary & other) const
|
||||||
|
{
|
||||||
|
return !isEqual(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::AcidBinary::operator=(const AcidBinary & other)
|
||||||
|
{
|
||||||
|
copyFrom(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
const u8 * nx::AcidBinary::getBytes() const
|
||||||
|
{
|
||||||
|
return mBinaryBlob.getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nx::AcidBinary::getSize() const
|
||||||
|
{
|
||||||
|
return mBinaryBlob.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::AcidBinary::exportBinary()
|
||||||
|
{
|
||||||
|
AciBinary::setHeaderOffset(crypto::rsa::kRsa2048Size); // not include signature
|
||||||
|
AciBinary::exportBinary();
|
||||||
|
mBinaryBlob.alloc(AciBinary::getSize() + crypto::rsa::kRsa2048Size * 2);
|
||||||
|
|
||||||
|
memcpy(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size, mEmbeddedPublicKey.modulus, crypto::rsa::kRsa2048Size);
|
||||||
|
memcpy(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size * 2, AciBinary::getBytes(), AciBinary::getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::AcidBinary::signBinary(const crypto::rsa::sRsa2048Key & key)
|
||||||
|
{
|
||||||
|
if (mBinaryBlob.getSize() == 0)
|
||||||
|
{
|
||||||
|
exportBinary();
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 hash[crypto::sha::kSha256HashLen];
|
||||||
|
crypto::sha::Sha256(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size, mBinaryBlob.getSize() - crypto::rsa::kRsa2048Size, hash);
|
||||||
|
|
||||||
|
if (crypto::rsa::pkcs::rsaSign(key, crypto::sha::HASH_SHA256, hash, mBinaryBlob.getBytes()) != 0)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Failed to sign ACID");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::AcidBinary::importBinary(const u8 * bytes, size_t len)
|
||||||
|
{
|
||||||
|
if (len <= crypto::rsa::kRsa2048Size*2)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "ACID binary too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
// import aci binary past sig + pubkey
|
||||||
|
AciBinary::importBinary(bytes + crypto::rsa::kRsa2048Size * 2, len - crypto::rsa::kRsa2048Size * 2);
|
||||||
|
|
||||||
|
// save internal copy
|
||||||
|
size_t acid_size = AciBinary::getSize() + crypto::rsa::kRsa2048Size * 2;
|
||||||
|
if (acid_size > len)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "ACID binary too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
mBinaryBlob.alloc(acid_size);
|
||||||
|
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
||||||
|
memcpy(mEmbeddedPublicKey.modulus, bytes + crypto::rsa::kRsa2048Size, crypto::rsa::kRsa2048Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::AcidBinary::verifyBinary(const crypto::rsa::sRsa2048Key & key)
|
||||||
|
{
|
||||||
|
if (mBinaryBlob.getSize() == 0)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "No ACID binary exists to verify");
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 hash[crypto::sha::kSha256HashLen];
|
||||||
|
crypto::sha::Sha256(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size, mBinaryBlob.getSize() - crypto::rsa::kRsa2048Size, hash);
|
||||||
|
|
||||||
|
if (crypto::rsa::pkcs::rsaVerify(key, crypto::sha::HASH_SHA256, hash, mBinaryBlob.getBytes()) != 0)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Failed to verify ACID");
|
||||||
|
}
|
||||||
|
}
|
51
lib/nx/AcidBinary.h
Normal file
51
lib/nx/AcidBinary.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/memory_blob.h>
|
||||||
|
#include <nx/ISerialiseableBinary.h>
|
||||||
|
#include <nx/AciBinary.h>
|
||||||
|
#include <crypto/rsa.h>
|
||||||
|
|
||||||
|
namespace nx
|
||||||
|
{
|
||||||
|
class AcidBinary :
|
||||||
|
public AciBinary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AcidBinary();
|
||||||
|
AcidBinary(const AcidBinary& other);
|
||||||
|
AcidBinary(const u8* bytes, size_t len);
|
||||||
|
|
||||||
|
bool operator==(const AcidBinary& other) const;
|
||||||
|
bool operator!=(const AcidBinary& other) const;
|
||||||
|
void operator=(const AcidBinary& other);
|
||||||
|
|
||||||
|
// to be used after export
|
||||||
|
const u8* getBytes() const;
|
||||||
|
size_t getSize() const;
|
||||||
|
|
||||||
|
// export/import binary
|
||||||
|
virtual void exportBinary();
|
||||||
|
void signBinary(const crypto::rsa::sRsa2048Key& key);
|
||||||
|
virtual void importBinary(const u8* bytes, size_t len);
|
||||||
|
void verifyBinary(const crypto::rsa::sRsa2048Key& key);
|
||||||
|
|
||||||
|
// variables
|
||||||
|
virtual void clear();
|
||||||
|
|
||||||
|
const crypto::rsa::sRsa2048Key& getPublicKey() const;
|
||||||
|
void setPublicKey(const crypto::rsa::sRsa2048Key& key);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "ACID_BINARY";
|
||||||
|
|
||||||
|
// raw binary
|
||||||
|
fnd::MemoryBlob mBinaryBlob;
|
||||||
|
|
||||||
|
// variables
|
||||||
|
crypto::rsa::sRsa2048Key mEmbeddedPublicKey;
|
||||||
|
|
||||||
|
bool isEqual(const AcidBinary& other) const;
|
||||||
|
void copyFrom(const AcidBinary& other);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -1,156 +1,102 @@
|
||||||
#include "FacBinary.h"
|
#include "FacBinary.h"
|
||||||
|
|
||||||
using namespace nx;
|
|
||||||
|
|
||||||
FacBinary::FacBinary() :
|
|
||||||
mHeader()
|
|
||||||
{
|
|
||||||
clearVariables();
|
|
||||||
}
|
|
||||||
|
|
||||||
FacBinary::FacBinary(const FacBinary & other)
|
nx::FacBinary::FacBinary()
|
||||||
{
|
{}
|
||||||
importBinary(other.getBytes(), other.getSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
FacBinary::FacBinary(const u8 * bytes, size_t len)
|
nx::FacBinary::FacBinary(const FacBinary & other)
|
||||||
{
|
|
||||||
importBinary(bytes, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FacBinary::operator==(const FacBinary & other) const
|
|
||||||
{
|
|
||||||
return isEqual(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FacBinary::operator!=(const FacBinary & other) const
|
|
||||||
{
|
|
||||||
return !isEqual(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FacBinary::operator=(const FacBinary & other)
|
|
||||||
{
|
{
|
||||||
copyFrom(other);
|
copyFrom(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8 * FacBinary::getBytes() const
|
nx::FacBinary::FacBinary(const u8 * bytes, size_t len)
|
||||||
|
{
|
||||||
|
importBinary(bytes, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nx::FacBinary::operator==(const FacBinary & other) const
|
||||||
|
{
|
||||||
|
return isEqual(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nx::FacBinary::operator!=(const FacBinary & other) const
|
||||||
|
{
|
||||||
|
return !isEqual(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::FacBinary::operator=(const FacBinary & other)
|
||||||
|
{
|
||||||
|
copyFrom(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
const u8 * nx::FacBinary::getBytes() const
|
||||||
{
|
{
|
||||||
return mBinaryBlob.getBytes();
|
return mBinaryBlob.getBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FacBinary::getSize() const
|
size_t nx::FacBinary::getSize() const
|
||||||
{
|
{
|
||||||
return mBinaryBlob.getSize();
|
return mBinaryBlob.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FacBinary::exportBinary()
|
void nx::FacBinary::exportBinary()
|
||||||
{
|
{
|
||||||
mHeader.setFsaRights(mFsaRights);
|
FacHeader::setContentOwnerIdSize(mContentOwnerIdList.getSize() * sizeof(u32));
|
||||||
mHeader.setContentOwnerIdSize(mContentOwnerIds.getSize() * sizeof(u32));
|
FacHeader::setSaveDataOwnerIdSize(mSaveDataOwnerIdList.getSize() * sizeof(u32));
|
||||||
mHeader.setSaveDataOwnerIdSize(mSaveDataOwnerIds.getSize() * sizeof(u32));
|
FacHeader::exportBinary();
|
||||||
mHeader.exportBinary();
|
|
||||||
|
|
||||||
mBinaryBlob.alloc(mHeader.getFacSize());
|
mBinaryBlob.alloc(getFacSize());
|
||||||
memcpy(mBinaryBlob.getBytes(), mHeader.getBytes(), mHeader.getSize());
|
memcpy(mBinaryBlob.getBytes(), FacHeader::getBytes(), FacHeader::getSize());
|
||||||
|
|
||||||
u32* rawContentOwnerIds = (u32*)(mBinaryBlob.getBytes() + mHeader.getContentOwnerIdOffset());
|
u32* rawContentOwnerIds = (u32*)(mBinaryBlob.getBytes() + FacHeader::getContentOwnerIdOffset());
|
||||||
for (size_t i = 0; i < mContentOwnerIds.getSize(); i++)
|
for (size_t i = 0; i < mContentOwnerIdList.getSize(); i++)
|
||||||
{
|
{
|
||||||
rawContentOwnerIds[i] = le_word(mContentOwnerIds[i]);
|
rawContentOwnerIds[i] = le_word(mContentOwnerIdList[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32* rawSaveDataOwnerIds = (u32*)(mBinaryBlob.getBytes() + mHeader.getSaveDataOwnerIdOffset());
|
u32* rawSaveDataOwnerIds = (u32*)(mBinaryBlob.getBytes() + FacHeader::getSaveDataOwnerIdOffset());
|
||||||
for (size_t i = 0; i < mSaveDataOwnerIds.getSize(); i++)
|
for (size_t i = 0; i < mSaveDataOwnerIdList.getSize(); i++)
|
||||||
{
|
{
|
||||||
rawSaveDataOwnerIds[i] = le_word(mSaveDataOwnerIds[i]);
|
rawSaveDataOwnerIds[i] = le_word(mSaveDataOwnerIdList[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FacBinary::importBinary(const u8 * bytes, size_t len)
|
void nx::FacBinary::importBinary(const u8 * bytes, size_t len)
|
||||||
{
|
{
|
||||||
clearVariables();
|
clear();
|
||||||
mHeader.importBinary(bytes, len);
|
FacHeader::importBinary(bytes, len);
|
||||||
if (mHeader.getFacSize() > len)
|
if (FacHeader::getFacSize() > len)
|
||||||
{
|
{
|
||||||
throw fnd::Exception(kModuleName, "FAC binary too small");
|
throw fnd::Exception(kModuleName, "FAC binary too small");
|
||||||
}
|
}
|
||||||
|
|
||||||
mBinaryBlob.alloc(mHeader.getFacSize());
|
mBinaryBlob.alloc(FacHeader::getFacSize());
|
||||||
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
||||||
|
|
||||||
mFsaRights = mHeader.getFsaRights();
|
u32* rawContentOwnerIds = (u32*)(mBinaryBlob.getBytes() + FacHeader::getContentOwnerIdOffset());
|
||||||
u32* rawContentOwnerIds = (u32*)(mBinaryBlob.getBytes() + mHeader.getContentOwnerIdOffset());
|
size_t rawContentOwnerIdNum = FacHeader::getContentOwnerIdSize() / sizeof(u32);
|
||||||
size_t rawContentOwnerIdNum = mHeader.getContentOwnerIdSize() / sizeof(u32);
|
|
||||||
for (size_t i = 0; i < rawContentOwnerIdNum; i++)
|
for (size_t i = 0; i < rawContentOwnerIdNum; i++)
|
||||||
{
|
{
|
||||||
addContentOwnerId(le_word(rawContentOwnerIds[i]));
|
mContentOwnerIdList.addElement(le_word(rawContentOwnerIds[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
u32* rawSaveDataOwnerIds = (u32*)(mBinaryBlob.getBytes() + mHeader.getSaveDataOwnerIdOffset());
|
u32* rawSaveDataOwnerIds = (u32*)(mBinaryBlob.getBytes() + FacHeader::getSaveDataOwnerIdOffset());
|
||||||
size_t rawSaveDataOwnerIdNum = mHeader.getSaveDataOwnerIdSize() / sizeof(u32);
|
size_t rawSaveDataOwnerIdNum = FacHeader::getSaveDataOwnerIdSize() / sizeof(u32);
|
||||||
for (size_t i = 0; i < rawSaveDataOwnerIdNum; i++)
|
for (size_t i = 0; i < rawSaveDataOwnerIdNum; i++)
|
||||||
{
|
{
|
||||||
addSaveDataOwnerId(le_word(rawSaveDataOwnerIds[i]));
|
mSaveDataOwnerIdList.addElement(le_word(rawSaveDataOwnerIds[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::FacBinary::clear()
|
bool nx::FacBinary::isEqual(const FacBinary & other) const
|
||||||
{
|
{
|
||||||
clearVariables();
|
return (FacHeader::operator==(other)) \
|
||||||
|
&& (mContentOwnerIdList == other.mContentOwnerIdList) \
|
||||||
|
&& (mSaveDataOwnerIdList == other.mSaveDataOwnerIdList);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FacBinary::isPermissionSet(FsAccessFlag flag) const
|
void nx::FacBinary::copyFrom(const FacBinary & other)
|
||||||
{
|
|
||||||
return (mFsaRights & flag) == flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FacBinary::addPermission(FsAccessFlag flag)
|
|
||||||
{
|
|
||||||
mFsaRights |= flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FacBinary::removePermission(FsAccessFlag flag)
|
|
||||||
{
|
|
||||||
mFsaRights &= ~(u64)flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fnd::List<u32>& FacBinary::getContentOwnerIds() const
|
|
||||||
{
|
|
||||||
return mContentOwnerIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FacBinary::addContentOwnerId(u32 id)
|
|
||||||
{
|
|
||||||
mContentOwnerIds.addElement(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
const fnd::List<u32>& FacBinary::getSaveDataOwnerIds() const
|
|
||||||
{
|
|
||||||
return mSaveDataOwnerIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FacBinary::addSaveDataOwnerId(u32 id)
|
|
||||||
{
|
|
||||||
mSaveDataOwnerIds.addElement(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FacBinary::clearVariables()
|
|
||||||
{
|
|
||||||
mHeader = FacHeader();
|
|
||||||
mFsaRights = 0;
|
|
||||||
mContentOwnerIds.clear();
|
|
||||||
mSaveDataOwnerIds.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FacBinary::isEqual(const FacBinary & other) const
|
|
||||||
{
|
|
||||||
return (mHeader == other.mHeader) \
|
|
||||||
&& (mFsaRights == other.mFsaRights) \
|
|
||||||
&& (mContentOwnerIds == other.mContentOwnerIds) \
|
|
||||||
&& (mSaveDataOwnerIds == other.mSaveDataOwnerIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FacBinary::copyFrom(const FacBinary & other)
|
|
||||||
{
|
{
|
||||||
if (other.getSize())
|
if (other.getSize())
|
||||||
{
|
{
|
||||||
|
@ -158,10 +104,35 @@ void FacBinary::copyFrom(const FacBinary & other)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mBinaryBlob.clear();
|
FacHeader::operator=(other);
|
||||||
mHeader = other.mHeader;
|
mContentOwnerIdList = other.mContentOwnerIdList;
|
||||||
mFsaRights = other.mFsaRights;
|
mSaveDataOwnerIdList = other.mSaveDataOwnerIdList;
|
||||||
mContentOwnerIds = other.mContentOwnerIds;
|
|
||||||
mSaveDataOwnerIds = other.mSaveDataOwnerIds;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nx::FacBinary::clear()
|
||||||
|
{
|
||||||
|
FacHeader::clear();
|
||||||
|
mContentOwnerIdList.clear();
|
||||||
|
mSaveDataOwnerIdList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
const fnd::List<u32>& nx::FacBinary::getContentOwnerIdList() const
|
||||||
|
{
|
||||||
|
return mContentOwnerIdList;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::FacBinary::setContentOwnerIdList(const fnd::List<u32>& list)
|
||||||
|
{
|
||||||
|
mContentOwnerIdList = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fnd::List<u32>& nx::FacBinary::getSaveDataOwnerIdList() const
|
||||||
|
{
|
||||||
|
return mSaveDataOwnerIdList;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::FacBinary::setSaveDataOwnerIdList(const fnd::List<u32>& list)
|
||||||
|
{
|
||||||
|
mSaveDataOwnerIdList = list;
|
||||||
|
}
|
||||||
|
|
|
@ -5,38 +5,13 @@
|
||||||
#include <nx/ISerialiseableBinary.h>
|
#include <nx/ISerialiseableBinary.h>
|
||||||
#include <nx/FacHeader.h>
|
#include <nx/FacHeader.h>
|
||||||
|
|
||||||
|
|
||||||
namespace nx
|
namespace nx
|
||||||
{
|
{
|
||||||
class FacBinary :
|
class FacBinary :
|
||||||
public ISerialiseableBinary
|
public FacHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum FsAccessFlag
|
|
||||||
{
|
|
||||||
FSA_APPLICATION_INFO = BIT(0),
|
|
||||||
FSA_BOOT_MODE_CONTROL = BIT(1),
|
|
||||||
FSA_CALIBRATION = BIT(2),
|
|
||||||
FSA_SYSTEM_SAVE_DATA = BIT(3),
|
|
||||||
FSA_GAME_CARD = BIT(4),
|
|
||||||
FSA_SAVE_DATA_BACKUP = BIT(5),
|
|
||||||
FSA_SAVE_DATA_MANAGEMENT = BIT(6),
|
|
||||||
FSA_BIS_ALL_RAW = BIT(7),
|
|
||||||
FSA_GAME_CARD_RAW = BIT(8),
|
|
||||||
FSA_GAME_CARD_PRIVATE = BIT(9),
|
|
||||||
FSA_SET_TIME = BIT(10),
|
|
||||||
FSA_CONTENT_MANAGER = BIT(11),
|
|
||||||
FSA_IMAGE_MANAGER = BIT(12),
|
|
||||||
FSA_CREATE_SAVE_DATA = BIT(13),
|
|
||||||
FSA_SYSTEM_SAVE_DATA_MANAGEMENT = BIT(14),
|
|
||||||
FSA_BIS_FILE_SYSTEM = BIT(15),
|
|
||||||
FSA_SYSTEM_UPDATE = BIT(16),
|
|
||||||
FSA_SAVE_DATA_META = BIT(17),
|
|
||||||
FSA_DEVICE_SAVE_CONTROL = BIT(19),
|
|
||||||
FSA_SETTINGS_CONTROL = BIT(20),
|
|
||||||
FSA_DEBUG = BIT(62),
|
|
||||||
FSA_FULL_PERMISSION = BIT(63),
|
|
||||||
};
|
|
||||||
|
|
||||||
FacBinary();
|
FacBinary();
|
||||||
FacBinary(const FacBinary& other);
|
FacBinary(const FacBinary& other);
|
||||||
FacBinary(const u8* bytes, size_t len);
|
FacBinary(const u8* bytes, size_t len);
|
||||||
|
@ -55,28 +30,24 @@ namespace nx
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
void clear();
|
void clear();
|
||||||
bool isPermissionSet(FsAccessFlag flag) const;
|
|
||||||
void addPermission(FsAccessFlag flag);
|
|
||||||
void removePermission(FsAccessFlag flag);
|
|
||||||
|
|
||||||
const fnd::List<u32>& getContentOwnerIds() const;
|
const fnd::List<u32>& getContentOwnerIdList() const;
|
||||||
void addContentOwnerId(u32 id);
|
void setContentOwnerIdList(const fnd::List<u32>& list);
|
||||||
|
|
||||||
|
const fnd::List<u32>& getSaveDataOwnerIdList() const;
|
||||||
|
void setSaveDataOwnerIdList(const fnd::List<u32>& list);
|
||||||
|
|
||||||
const fnd::List<u32>& getSaveDataOwnerIds() const;
|
|
||||||
void addSaveDataOwnerId(u32 id);
|
|
||||||
private:
|
private:
|
||||||
const std::string kModuleName = "FAC_BINARY";
|
const std::string kModuleName = "FAC_BINARY";
|
||||||
|
static const u32 kFacFormatVersion = 1;
|
||||||
|
|
||||||
// raw binary
|
// raw binary
|
||||||
fnd::MemoryBlob mBinaryBlob;
|
fnd::MemoryBlob mBinaryBlob;
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
FacHeader mHeader;
|
fnd::List<u32> mContentOwnerIdList;
|
||||||
u64 mFsaRights;
|
fnd::List<u32> mSaveDataOwnerIdList;
|
||||||
fnd::List<u32> mContentOwnerIds;
|
|
||||||
fnd::List<u32> mSaveDataOwnerIds;
|
|
||||||
|
|
||||||
void clearVariables();
|
|
||||||
bool isEqual(const FacBinary& other) const;
|
bool isEqual(const FacBinary& other) const;
|
||||||
void copyFrom(const FacBinary& other);
|
void copyFrom(const FacBinary& other);
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,17 +2,20 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
nx::FacHeader::FacHeader()
|
nx::FacHeader::FacHeader() :
|
||||||
|
mFsaRights()
|
||||||
{
|
{
|
||||||
clearVariables();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
nx::FacHeader::FacHeader(const FacHeader & other)
|
nx::FacHeader::FacHeader(const FacHeader & other) :
|
||||||
|
mFsaRights()
|
||||||
{
|
{
|
||||||
copyFrom(other);
|
copyFrom(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
nx::FacHeader::FacHeader(const u8 * bytes, size_t len)
|
nx::FacHeader::FacHeader(const u8 * bytes, size_t len) :
|
||||||
|
mFsaRights()
|
||||||
{
|
{
|
||||||
importBinary(bytes, len);
|
importBinary(bytes, len);
|
||||||
}
|
}
|
||||||
|
@ -47,8 +50,18 @@ void nx::FacHeader::exportBinary()
|
||||||
mBinaryBlob.alloc(sizeof(sFacHeader));
|
mBinaryBlob.alloc(sizeof(sFacHeader));
|
||||||
sFacHeader* hdr = (sFacHeader*)mBinaryBlob.getBytes();
|
sFacHeader* hdr = (sFacHeader*)mBinaryBlob.getBytes();
|
||||||
|
|
||||||
hdr->set_version(kFacFormatVersion);
|
if (mVersion != kFacFormatVersion)
|
||||||
hdr->set_fac_flags(mFsaRights);
|
{
|
||||||
|
fnd::Exception(kModuleName, "Unsupported format version");
|
||||||
|
}
|
||||||
|
hdr->set_version(mVersion);
|
||||||
|
|
||||||
|
u64 flag = 0;
|
||||||
|
for (size_t i = 0; i < mFsaRights.getSize(); i++)
|
||||||
|
{
|
||||||
|
flag |= BIT((u64)mFsaRights[i]);
|
||||||
|
}
|
||||||
|
hdr->set_fac_flags(flag);
|
||||||
|
|
||||||
calculateOffsets();
|
calculateOffsets();
|
||||||
hdr->content_owner_ids().set_start(mContentOwnerIdPos.offset);
|
hdr->content_owner_ids().set_start(mContentOwnerIdPos.offset);
|
||||||
|
@ -72,8 +85,16 @@ void nx::FacHeader::importBinary(const u8 * bytes, size_t len)
|
||||||
{
|
{
|
||||||
throw fnd::Exception(kModuleName, "Unsupported FAC format version");
|
throw fnd::Exception(kModuleName, "Unsupported FAC format version");
|
||||||
}
|
}
|
||||||
|
mVersion = hdr->version();
|
||||||
|
|
||||||
mFsaRights = hdr->fac_flags();
|
clear();
|
||||||
|
for (u64 i = 0; i < 64; i++)
|
||||||
|
{
|
||||||
|
if ((hdr->fac_flags() >> i) & 1)
|
||||||
|
{
|
||||||
|
mFsaRights.addElement((FsAccessFlag)i);
|
||||||
|
}
|
||||||
|
}
|
||||||
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() ? hdr->content_owner_ids().end() - hdr->content_owner_ids().start() : 0;
|
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();
|
||||||
|
@ -82,7 +103,11 @@ void nx::FacHeader::importBinary(const u8 * bytes, size_t len)
|
||||||
|
|
||||||
void nx::FacHeader::clear()
|
void nx::FacHeader::clear()
|
||||||
{
|
{
|
||||||
clearVariables();
|
mFsaRights.clear();
|
||||||
|
mContentOwnerIdPos.offset = 0;
|
||||||
|
mContentOwnerIdPos.size = 0;
|
||||||
|
mSaveDataOwnerIdPos.offset = 0;
|
||||||
|
mSaveDataOwnerIdPos.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nx::FacHeader::getFacSize() const
|
size_t nx::FacHeader::getFacSize() const
|
||||||
|
@ -92,14 +117,28 @@ size_t nx::FacHeader::getFacSize() const
|
||||||
return MAX(MAX(savedata, content), sizeof(sFacHeader));
|
return MAX(MAX(savedata, content), sizeof(sFacHeader));
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 nx::FacHeader::getFsaRights() const
|
u32 nx::FacHeader::getFormatVersion() const
|
||||||
|
{
|
||||||
|
return mVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::FacHeader::setFormatVersion(u32 version)
|
||||||
|
{
|
||||||
|
mVersion = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fnd::List<nx::FacHeader::FsAccessFlag>& nx::FacHeader::getFsaRightsList() const
|
||||||
{
|
{
|
||||||
return mFsaRights;
|
return mFsaRights;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::FacHeader::setFsaRights(u64 flag)
|
void nx::FacHeader::setFsaRightsList(const fnd::List<FsAccessFlag>& list)
|
||||||
{
|
{
|
||||||
mFsaRights = flag;
|
mFsaRights.clear();
|
||||||
|
for (size_t i = 0; i < list.getSize(); i++)
|
||||||
|
{
|
||||||
|
mFsaRights.hasElement(list[i]) ? mFsaRights.addElement(list[i]) : throw fnd::Exception(kModuleName, "FSA right already exists");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nx::FacHeader::getContentOwnerIdOffset() const
|
size_t nx::FacHeader::getContentOwnerIdOffset() const
|
||||||
|
@ -132,15 +171,6 @@ void nx::FacHeader::setSaveDataOwnerIdSize(size_t size)
|
||||||
mSaveDataOwnerIdPos.size = size;
|
mSaveDataOwnerIdPos.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::FacHeader::clearVariables()
|
|
||||||
{
|
|
||||||
mFsaRights = 0;
|
|
||||||
mContentOwnerIdPos.offset = 0;
|
|
||||||
mContentOwnerIdPos.size = 0;
|
|
||||||
mSaveDataOwnerIdPos.offset = 0;
|
|
||||||
mSaveDataOwnerIdPos.size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nx::FacHeader::calculateOffsets()
|
void nx::FacHeader::calculateOffsets()
|
||||||
{
|
{
|
||||||
mContentOwnerIdPos.offset = align(sizeof(sFacHeader), 4);
|
mContentOwnerIdPos.offset = align(sizeof(sFacHeader), 4);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fnd/memory_blob.h>
|
#include <fnd/memory_blob.h>
|
||||||
|
#include <fnd/List.h>
|
||||||
#include <nx/ISerialiseableBinary.h>
|
#include <nx/ISerialiseableBinary.h>
|
||||||
|
|
||||||
namespace nx
|
namespace nx
|
||||||
|
@ -9,6 +10,32 @@ namespace nx
|
||||||
public ISerialiseableBinary
|
public ISerialiseableBinary
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum FsAccessFlag
|
||||||
|
{
|
||||||
|
FSA_APPLICATION_INFO,
|
||||||
|
FSA_BOOT_MODE_CONTROL,
|
||||||
|
FSA_CALIBRATION,
|
||||||
|
FSA_SYSTEM_SAVE_DATA,
|
||||||
|
FSA_GAME_CARD,
|
||||||
|
FSA_SAVE_DATA_BACKUP,
|
||||||
|
FSA_SAVE_DATA_MANAGEMENT,
|
||||||
|
FSA_BIS_ALL_RAW,
|
||||||
|
FSA_GAME_CARD_RAW,
|
||||||
|
FSA_GAME_CARD_PRIVATE,
|
||||||
|
FSA_SET_TIME,
|
||||||
|
FSA_CONTENT_MANAGER,
|
||||||
|
FSA_IMAGE_MANAGER,
|
||||||
|
FSA_CREATE_SAVE_DATA,
|
||||||
|
FSA_SYSTEM_SAVE_DATA_MANAGEMENT,
|
||||||
|
FSA_BIS_FILE_SYSTEM,
|
||||||
|
FSA_SYSTEM_UPDATE,
|
||||||
|
FSA_SAVE_DATA_META,
|
||||||
|
FSA_DEVICE_SAVE_CONTROL,
|
||||||
|
FSA_SETTINGS_CONTROL,
|
||||||
|
FSA_DEBUG = 62,
|
||||||
|
FSA_FULL_PERMISSION = 63,
|
||||||
|
};
|
||||||
|
|
||||||
FacHeader();
|
FacHeader();
|
||||||
FacHeader(const FacHeader& other);
|
FacHeader(const FacHeader& other);
|
||||||
FacHeader(const u8* bytes, size_t len);
|
FacHeader(const u8* bytes, size_t len);
|
||||||
|
@ -29,8 +56,11 @@ namespace nx
|
||||||
void clear();
|
void clear();
|
||||||
size_t getFacSize() const;
|
size_t getFacSize() const;
|
||||||
|
|
||||||
u64 getFsaRights() const;
|
u32 getFormatVersion() const;
|
||||||
void setFsaRights(u64 flag);
|
void setFormatVersion(u32 version);
|
||||||
|
|
||||||
|
const fnd::List<FsAccessFlag>& getFsaRightsList() const;
|
||||||
|
void setFsaRightsList(const fnd::List<FsAccessFlag>& list);
|
||||||
|
|
||||||
size_t getContentOwnerIdOffset() const;
|
size_t getContentOwnerIdOffset() const;
|
||||||
size_t getContentOwnerIdSize() const;
|
size_t getContentOwnerIdSize() const;
|
||||||
|
@ -81,14 +111,14 @@ namespace nx
|
||||||
fnd::MemoryBlob mBinaryBlob;
|
fnd::MemoryBlob mBinaryBlob;
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
u64 mFsaRights;
|
u32 mVersion;
|
||||||
|
fnd::List<FsAccessFlag> mFsaRights;
|
||||||
struct sSection
|
struct sSection
|
||||||
{
|
{
|
||||||
size_t offset;
|
size_t offset;
|
||||||
size_t size;
|
size_t size;
|
||||||
} mContentOwnerIdPos, mSaveDataOwnerIdPos;
|
} mContentOwnerIdPos, mSaveDataOwnerIdPos;
|
||||||
|
|
||||||
void clearVariables();
|
|
||||||
void calculateOffsets();
|
void calculateOffsets();
|
||||||
bool isEqual(const FacHeader& other) const;
|
bool isEqual(const FacHeader& other) const;
|
||||||
void copyFrom(const FacHeader& other);
|
void copyFrom(const FacHeader& other);
|
||||||
|
|
|
@ -131,7 +131,15 @@ void nx::KcBinary::importBinary(const u8 * bytes, size_t len)
|
||||||
|
|
||||||
void nx::KcBinary::clear()
|
void nx::KcBinary::clear()
|
||||||
{
|
{
|
||||||
clearVariables();
|
mBinaryBlob.clear();
|
||||||
|
mThreadInfo.clear();
|
||||||
|
mSystemCalls.clear();
|
||||||
|
mMemoryMap.clear();
|
||||||
|
mInterupts.clear();
|
||||||
|
mMiscParams.clear();
|
||||||
|
mKernelVersion.clear();
|
||||||
|
mHandleTableSize.clear();
|
||||||
|
mMiscFlags.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
const nx::ThreadInfoHandler & nx::KcBinary::getThreadInfo() const
|
const nx::ThreadInfoHandler & nx::KcBinary::getThreadInfo() const
|
||||||
|
@ -214,19 +222,6 @@ nx::MiscFlagsHandler & nx::KcBinary::getMiscFlags()
|
||||||
return mMiscFlags;
|
return mMiscFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::KcBinary::clearVariables()
|
|
||||||
{
|
|
||||||
mBinaryBlob.clear();
|
|
||||||
mThreadInfo.clear();
|
|
||||||
mSystemCalls.clear();
|
|
||||||
mMemoryMap.clear();
|
|
||||||
mInterupts.clear();
|
|
||||||
mMiscParams.clear();
|
|
||||||
mKernelVersion.clear();
|
|
||||||
mHandleTableSize.clear();
|
|
||||||
mMiscFlags.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nx::KcBinary::isEqual(const KcBinary & other) const
|
bool nx::KcBinary::isEqual(const KcBinary & other) const
|
||||||
{
|
{
|
||||||
return (mThreadInfo == other.mThreadInfo) \
|
return (mThreadInfo == other.mThreadInfo) \
|
||||||
|
|
|
@ -41,7 +41,7 @@ void NcaHeader::importBinary(const u8 * bytes, size_t len)
|
||||||
throw fnd::Exception(kModuleName, "NCA header size is too small");
|
throw fnd::Exception(kModuleName, "NCA header size is too small");
|
||||||
}
|
}
|
||||||
|
|
||||||
clearVariables();
|
clear();
|
||||||
|
|
||||||
mBinaryBlob.alloc(sizeof(sNcaHeader));
|
mBinaryBlob.alloc(sizeof(sNcaHeader));
|
||||||
memcpy(mBinaryBlob.getBytes(), bytes, sizeof(sNcaHeader));
|
memcpy(mBinaryBlob.getBytes(), bytes, sizeof(sNcaHeader));
|
||||||
|
@ -78,7 +78,12 @@ void NcaHeader::importBinary(const u8 * bytes, size_t len)
|
||||||
|
|
||||||
void nx::NcaHeader::clear()
|
void nx::NcaHeader::clear()
|
||||||
{
|
{
|
||||||
clearVariables();
|
mBlockSize = 0;
|
||||||
|
mNcaSize = 0;
|
||||||
|
mProgramId = 0;
|
||||||
|
mUnk0 = 0;
|
||||||
|
mSections.clear();
|
||||||
|
mAesKeys.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 NcaHeader::getNcaSize() const
|
u64 NcaHeader::getNcaSize() const
|
||||||
|
@ -135,16 +140,6 @@ void NcaHeader::addKey(const crypto::aes::sAes128Key & key)
|
||||||
mAesKeys.addElement(key);
|
mAesKeys.addElement(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NcaHeader::clearVariables()
|
|
||||||
{
|
|
||||||
mBlockSize = 0;
|
|
||||||
mNcaSize = 0;
|
|
||||||
mProgramId = 0;
|
|
||||||
mUnk0 = 0;
|
|
||||||
mSections.clear();
|
|
||||||
mAesKeys.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 NcaHeader::blockNumToSize(u32 block_num) const
|
u64 NcaHeader::blockNumToSize(u32 block_num) const
|
||||||
{
|
{
|
||||||
return block_num*mBlockSize;
|
return block_num*mBlockSize;
|
||||||
|
@ -185,7 +180,7 @@ void NcaHeader::copyFrom(const NcaHeader & other)
|
||||||
|
|
||||||
NcaHeader::NcaHeader()
|
NcaHeader::NcaHeader()
|
||||||
{
|
{
|
||||||
clearVariables();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
NcaHeader::NcaHeader(const NcaHeader & other)
|
NcaHeader::NcaHeader(const NcaHeader & other)
|
||||||
|
|
|
@ -149,7 +149,6 @@ namespace nx
|
||||||
fnd::List<sSection> mSections;
|
fnd::List<sSection> mSections;
|
||||||
fnd::List<crypto::aes::sAes128Key> mAesKeys;
|
fnd::List<crypto::aes::sAes128Key> mAesKeys;
|
||||||
|
|
||||||
void clearVariables();
|
|
||||||
u64 blockNumToSize(u32 block_num) const;
|
u64 blockNumToSize(u32 block_num) const;
|
||||||
u32 sizeToBlockNum(u64 real_size) const;
|
u32 sizeToBlockNum(u64 real_size) const;
|
||||||
bool isEqual(const NcaHeader& other) const;
|
bool isEqual(const NcaHeader& other) const;
|
||||||
|
|
136
lib/nx/NpdmBinary.cpp
Normal file
136
lib/nx/NpdmBinary.cpp
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
#include "NpdmBinary.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
nx::NpdmBinary::NpdmBinary() :
|
||||||
|
mAci(),
|
||||||
|
mAcid()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
nx::NpdmBinary::NpdmBinary(const NpdmBinary & other) :
|
||||||
|
mAci(),
|
||||||
|
mAcid()
|
||||||
|
{
|
||||||
|
copyFrom(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
nx::NpdmBinary::NpdmBinary(const u8 * bytes, size_t len) :
|
||||||
|
mAci(),
|
||||||
|
mAcid()
|
||||||
|
{
|
||||||
|
importBinary(bytes, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nx::NpdmBinary::operator==(const NpdmBinary & other) const
|
||||||
|
{
|
||||||
|
return isEqual(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nx::NpdmBinary::operator!=(const NpdmBinary & other) const
|
||||||
|
{
|
||||||
|
return !isEqual(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::NpdmBinary::operator=(const NpdmBinary & other)
|
||||||
|
{
|
||||||
|
copyFrom(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::NpdmBinary::exportBinary()
|
||||||
|
{
|
||||||
|
mAci.exportBinary();
|
||||||
|
mAcid.exportBinary();
|
||||||
|
|
||||||
|
setAciSize(mAci.getSize());
|
||||||
|
setAcidSize(mAcid.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::NpdmBinary::importBinary(const u8 * bytes, size_t len)
|
||||||
|
{
|
||||||
|
// clear
|
||||||
|
clear();
|
||||||
|
|
||||||
|
// import header
|
||||||
|
NpdmHeader::importBinary(bytes, len);
|
||||||
|
|
||||||
|
// check size
|
||||||
|
if (getNpdmSize() > len)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "NPDM binary too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
// save local copy
|
||||||
|
mBinaryBlob.alloc(getNpdmSize());
|
||||||
|
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
||||||
|
|
||||||
|
// import Aci/Acid
|
||||||
|
if (getAciPos().size)
|
||||||
|
{
|
||||||
|
mAci.importBinary(mBinaryBlob.getBytes() + getAciPos().offset, getAciPos().size);
|
||||||
|
}
|
||||||
|
if (getAcidPos().size)
|
||||||
|
{
|
||||||
|
mAcid.importBinary(mBinaryBlob.getBytes() + getAcidPos().offset, getAcidPos().size);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::NpdmBinary::clear()
|
||||||
|
{
|
||||||
|
NpdmHeader::clear();
|
||||||
|
mAci.clear();
|
||||||
|
mAcid.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nx::AciBinary & nx::NpdmBinary::getAci() const
|
||||||
|
{
|
||||||
|
return mAci;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::NpdmBinary::setAci(const AciBinary & aci)
|
||||||
|
{
|
||||||
|
mAci = aci;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nx::AcidBinary & nx::NpdmBinary::getAcid() const
|
||||||
|
{
|
||||||
|
return mAcid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::NpdmBinary::setAcid(const AcidBinary & acid)
|
||||||
|
{
|
||||||
|
mAcid = acid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nx::NpdmBinary::isEqual(const NpdmBinary & other) const
|
||||||
|
{
|
||||||
|
return (NpdmHeader::operator==(other)) \
|
||||||
|
&& (mAci == other.mAci) \
|
||||||
|
&& (mAcid == other.mAcid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::NpdmBinary::copyFrom(const NpdmBinary & other)
|
||||||
|
{
|
||||||
|
if (other.getSize())
|
||||||
|
{
|
||||||
|
importBinary(other.getBytes(), other.getSize());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NpdmHeader::operator=(other);
|
||||||
|
mAci = other.mAci;
|
||||||
|
mAcid = other.mAcid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const u8 * nx::NpdmBinary::getBytes() const
|
||||||
|
{
|
||||||
|
return mBinaryBlob.getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nx::NpdmBinary::getSize() const
|
||||||
|
{
|
||||||
|
return mBinaryBlob.getSize();
|
||||||
|
}
|
55
lib/nx/NpdmBinary.h
Normal file
55
lib/nx/NpdmBinary.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/memory_blob.h>
|
||||||
|
#include <fnd/List.h>
|
||||||
|
#include <nx/ISerialiseableBinary.h>
|
||||||
|
#include <nx/NpdmHeader.h>
|
||||||
|
#include <nx/AciBinary.h>
|
||||||
|
#include <nx/AcidBinary.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace nx
|
||||||
|
{
|
||||||
|
class NpdmBinary :
|
||||||
|
public NpdmHeader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NpdmBinary();
|
||||||
|
NpdmBinary(const NpdmBinary& other);
|
||||||
|
NpdmBinary(const u8* bytes, size_t len);
|
||||||
|
|
||||||
|
bool operator==(const NpdmBinary& other) const;
|
||||||
|
bool operator!=(const NpdmBinary& other) const;
|
||||||
|
void operator=(const NpdmBinary& other);
|
||||||
|
|
||||||
|
// to be used after export
|
||||||
|
const u8* getBytes() const;
|
||||||
|
size_t getSize() const;
|
||||||
|
|
||||||
|
// export/import binary
|
||||||
|
void exportBinary();
|
||||||
|
void importBinary(const u8* bytes, size_t len);
|
||||||
|
|
||||||
|
// variables
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
const AciBinary& getAci() const;
|
||||||
|
void setAci(const AciBinary& aci);
|
||||||
|
|
||||||
|
const AcidBinary& getAcid() const;
|
||||||
|
void setAcid(const AcidBinary& acid);
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "NPDM_BINARY";
|
||||||
|
|
||||||
|
// raw binary
|
||||||
|
fnd::MemoryBlob mBinaryBlob;
|
||||||
|
|
||||||
|
// variables
|
||||||
|
AciBinary mAci;
|
||||||
|
AcidBinary mAcid;
|
||||||
|
|
||||||
|
bool isEqual(const NpdmBinary& other) const;
|
||||||
|
void copyFrom(const NpdmBinary& other);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
nx::NpdmHeader::NpdmHeader()
|
nx::NpdmHeader::NpdmHeader()
|
||||||
{
|
{
|
||||||
clearVariables();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
nx::NpdmHeader::NpdmHeader(const NpdmHeader & other)
|
nx::NpdmHeader::NpdmHeader(const NpdmHeader & other)
|
||||||
|
@ -42,23 +42,6 @@ size_t nx::NpdmHeader::getSize() const
|
||||||
return mBinaryBlob.getSize();
|
return mBinaryBlob.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::NpdmHeader::clearVariables()
|
|
||||||
{
|
|
||||||
mBinaryBlob.clear();
|
|
||||||
mInstructionType = INSTR_64BIT;
|
|
||||||
mProcAddressSpaceType = ADDR_SPACE_64BIT;
|
|
||||||
mMainThreadPriority = 0;
|
|
||||||
mMainThreadCoreNumber = 0;
|
|
||||||
mVersion = 0;
|
|
||||||
mMainThreadStackSize = 0;
|
|
||||||
mName.clear();
|
|
||||||
mProductCode.clear();
|
|
||||||
mAciPos.offset = 0;
|
|
||||||
mAciPos.size = 0;
|
|
||||||
mAcidPos.offset = 0;
|
|
||||||
mAcidPos.size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nx::NpdmHeader::calculateOffsets()
|
void nx::NpdmHeader::calculateOffsets()
|
||||||
{
|
{
|
||||||
mAcidPos.offset = align(sizeof(sNpdmHeader), kNpdmAlignSize);
|
mAcidPos.offset = align(sizeof(sNpdmHeader), kNpdmAlignSize);
|
||||||
|
@ -70,7 +53,7 @@ bool nx::NpdmHeader::isEqual(const NpdmHeader & other) const
|
||||||
return (mInstructionType == other.mInstructionType) \
|
return (mInstructionType == other.mInstructionType) \
|
||||||
&& (mProcAddressSpaceType == other.mProcAddressSpaceType) \
|
&& (mProcAddressSpaceType == other.mProcAddressSpaceType) \
|
||||||
&& (mMainThreadPriority == other.mMainThreadPriority) \
|
&& (mMainThreadPriority == other.mMainThreadPriority) \
|
||||||
&& (mMainThreadCoreNumber == other.mMainThreadCoreNumber) \
|
&& (mMainThreadCpuId == other.mMainThreadCpuId) \
|
||||||
&& (mVersion == other.mVersion) \
|
&& (mVersion == other.mVersion) \
|
||||||
&& (mMainThreadStackSize == other.mMainThreadStackSize) \
|
&& (mMainThreadStackSize == other.mMainThreadStackSize) \
|
||||||
&& (mName == other.mName) \
|
&& (mName == other.mName) \
|
||||||
|
@ -90,7 +73,7 @@ void nx::NpdmHeader::copyFrom(const NpdmHeader & other)
|
||||||
mInstructionType = other.mInstructionType;
|
mInstructionType = other.mInstructionType;
|
||||||
mProcAddressSpaceType = other.mProcAddressSpaceType;
|
mProcAddressSpaceType = other.mProcAddressSpaceType;
|
||||||
mMainThreadPriority = other.mMainThreadPriority;
|
mMainThreadPriority = other.mMainThreadPriority;
|
||||||
mMainThreadCoreNumber = other.mMainThreadCoreNumber;
|
mMainThreadCpuId = other.mMainThreadCpuId;
|
||||||
mVersion = other.mVersion;
|
mVersion = other.mVersion;
|
||||||
mMainThreadStackSize = other.mMainThreadStackSize;
|
mMainThreadStackSize = other.mMainThreadStackSize;
|
||||||
mName = other.mName;
|
mName = other.mName;
|
||||||
|
@ -109,7 +92,7 @@ void nx::NpdmHeader::exportBinary()
|
||||||
u8 flag = ((u8)(mInstructionType & 1) | (u8)((mProcAddressSpaceType & 3) << 1)) & 0xf;
|
u8 flag = ((u8)(mInstructionType & 1) | (u8)((mProcAddressSpaceType & 3) << 1)) & 0xf;
|
||||||
hdr->set_flags(flag);
|
hdr->set_flags(flag);
|
||||||
hdr->set_main_thread_priority(mMainThreadPriority);
|
hdr->set_main_thread_priority(mMainThreadPriority);
|
||||||
hdr->set_main_thread_core_number(mMainThreadCoreNumber);
|
hdr->set_main_thread_cpu_id(mMainThreadCpuId);
|
||||||
hdr->set_version(mVersion);
|
hdr->set_version(mVersion);
|
||||||
hdr->set_main_thread_stack_size(mMainThreadStackSize);
|
hdr->set_main_thread_stack_size(mMainThreadStackSize);
|
||||||
hdr->set_name(mName.c_str());
|
hdr->set_name(mName.c_str());
|
||||||
|
@ -129,7 +112,7 @@ void nx::NpdmHeader::importBinary(const u8 * bytes, size_t len)
|
||||||
throw fnd::Exception(kModuleName, "NPDM header too small");
|
throw fnd::Exception(kModuleName, "NPDM header too small");
|
||||||
}
|
}
|
||||||
|
|
||||||
clearVariables();
|
clear();
|
||||||
|
|
||||||
mBinaryBlob.alloc(sizeof(sNpdmHeader));
|
mBinaryBlob.alloc(sizeof(sNpdmHeader));
|
||||||
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
||||||
|
@ -144,11 +127,19 @@ void nx::NpdmHeader::importBinary(const u8 * bytes, size_t len)
|
||||||
mInstructionType = (InstructionType)(flag & 1);
|
mInstructionType = (InstructionType)(flag & 1);
|
||||||
mProcAddressSpaceType = (ProcAddrSpaceType)((flag >> 1) & 3);
|
mProcAddressSpaceType = (ProcAddrSpaceType)((flag >> 1) & 3);
|
||||||
mMainThreadPriority = hdr->main_thread_priority();
|
mMainThreadPriority = hdr->main_thread_priority();
|
||||||
mMainThreadCoreNumber = hdr->main_thread_core_number();
|
mMainThreadCpuId = hdr->main_thread_cpu_id();
|
||||||
mVersion = hdr->version();
|
mVersion = hdr->version();
|
||||||
mMainThreadStackSize = hdr->main_thread_stack_size();
|
mMainThreadStackSize = hdr->main_thread_stack_size();
|
||||||
mName = std::string(hdr->name(), kNameMaxLen);
|
mName = std::string(hdr->name(), kNameMaxLen);
|
||||||
|
if (mName[0] == '\0')
|
||||||
|
{
|
||||||
|
mName.clear();
|
||||||
|
}
|
||||||
mProductCode = std::string(hdr->product_code(), kProductCodeMaxLen);
|
mProductCode = std::string(hdr->product_code(), kProductCodeMaxLen);
|
||||||
|
if (mProductCode[0] == '\0')
|
||||||
|
{
|
||||||
|
mProductCode.clear();
|
||||||
|
}
|
||||||
mAciPos.offset = hdr->aci().offset();
|
mAciPos.offset = hdr->aci().offset();
|
||||||
mAciPos.size = hdr->aci().size();
|
mAciPos.size = hdr->aci().size();
|
||||||
mAcidPos.offset = hdr->acid().offset();
|
mAcidPos.offset = hdr->acid().offset();
|
||||||
|
@ -157,7 +148,19 @@ void nx::NpdmHeader::importBinary(const u8 * bytes, size_t len)
|
||||||
|
|
||||||
void nx::NpdmHeader::clear()
|
void nx::NpdmHeader::clear()
|
||||||
{
|
{
|
||||||
clearVariables();
|
mBinaryBlob.clear();
|
||||||
|
mInstructionType = INSTR_64BIT;
|
||||||
|
mProcAddressSpaceType = ADDR_SPACE_64BIT;
|
||||||
|
mMainThreadPriority = 0;
|
||||||
|
mMainThreadCpuId = 0;
|
||||||
|
mVersion = 0;
|
||||||
|
mMainThreadStackSize = 0;
|
||||||
|
mName.clear();
|
||||||
|
mProductCode.clear();
|
||||||
|
mAciPos.offset = 0;
|
||||||
|
mAciPos.size = 0;
|
||||||
|
mAcidPos.offset = 0;
|
||||||
|
mAcidPos.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nx::NpdmHeader::getNpdmSize() const
|
size_t nx::NpdmHeader::getNpdmSize() const
|
||||||
|
@ -200,14 +203,14 @@ void nx::NpdmHeader::setMainThreadPriority(u8 priority)
|
||||||
mMainThreadPriority = priority;
|
mMainThreadPriority = priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 nx::NpdmHeader::getMainThreadCoreNumber() const
|
u8 nx::NpdmHeader::getMainThreadCpuId() const
|
||||||
{
|
{
|
||||||
return mMainThreadCoreNumber;
|
return mMainThreadCpuId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::NpdmHeader::setMainThreadCoreNumber(u8 core_num)
|
void nx::NpdmHeader::setMainThreadCpuId(u8 core_num)
|
||||||
{
|
{
|
||||||
mMainThreadCoreNumber = core_num;
|
mMainThreadCpuId = core_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 nx::NpdmHeader::getVersion() const
|
u32 nx::NpdmHeader::getVersion() const
|
||||||
|
@ -265,7 +268,7 @@ const nx::NpdmHeader::sSection & nx::NpdmHeader::getAciPos() const
|
||||||
return mAciPos;
|
return mAciPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::NpdmHeader::setSetAciSize(size_t size)
|
void nx::NpdmHeader::setAciSize(size_t size)
|
||||||
{
|
{
|
||||||
mAciPos.size = size;
|
mAciPos.size = size;
|
||||||
}
|
}
|
||||||
|
@ -275,7 +278,7 @@ const nx::NpdmHeader::sSection & nx::NpdmHeader::getAcidPos() const
|
||||||
return mAcidPos;
|
return mAcidPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::NpdmHeader::setSetAcidSize(size_t size)
|
void nx::NpdmHeader::setAcidSize(size_t size)
|
||||||
{
|
{
|
||||||
mAcidPos.size = size;
|
mAcidPos.size = size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,8 +76,8 @@ namespace nx
|
||||||
u8 getMainThreadPriority() const;
|
u8 getMainThreadPriority() const;
|
||||||
void setMainThreadPriority(u8 priority);
|
void setMainThreadPriority(u8 priority);
|
||||||
|
|
||||||
u8 getMainThreadCoreNumber() const;
|
u8 getMainThreadCpuId() const;
|
||||||
void setMainThreadCoreNumber(u8 core_num);
|
void setMainThreadCpuId(u8 cpu_id);
|
||||||
|
|
||||||
u32 getVersion() const;
|
u32 getVersion() const;
|
||||||
void setVersion(u32 version);
|
void setVersion(u32 version);
|
||||||
|
@ -92,10 +92,10 @@ namespace nx
|
||||||
void setProductCode(const std::string& product_code);
|
void setProductCode(const std::string& product_code);
|
||||||
|
|
||||||
const sSection& getAciPos() const;
|
const sSection& getAciPos() const;
|
||||||
void setSetAciSize(size_t size);
|
void setAciSize(size_t size);
|
||||||
|
|
||||||
const sSection& getAcidPos() const;
|
const sSection& getAcidPos() const;
|
||||||
void setSetAcidSize(size_t size);
|
void setAcidSize(size_t size);
|
||||||
private:
|
private:
|
||||||
const std::string kModuleName = "NPDM_HEADER";
|
const std::string kModuleName = "NPDM_HEADER";
|
||||||
const std::string kNpdmStructSig = "META";
|
const std::string kNpdmStructSig = "META";
|
||||||
|
@ -114,7 +114,7 @@ namespace nx
|
||||||
u8 flags_;
|
u8 flags_;
|
||||||
u8 reserved_1;
|
u8 reserved_1;
|
||||||
u8 main_thread_priority_; // 0-63 inclusive
|
u8 main_thread_priority_; // 0-63 inclusive
|
||||||
u8 main_thread_core_number_;
|
u8 main_thread_cpu_id_;
|
||||||
u8 reserved_2[8];
|
u8 reserved_2[8];
|
||||||
u32 version_;
|
u32 version_;
|
||||||
u32 main_thread_stack_size_; // default 4096
|
u32 main_thread_stack_size_; // default 4096
|
||||||
|
@ -144,8 +144,8 @@ namespace nx
|
||||||
u8 main_thread_priority() const { return main_thread_priority_; }
|
u8 main_thread_priority() const { return main_thread_priority_; }
|
||||||
void set_main_thread_priority(u8 priority) { main_thread_priority_ = priority; }
|
void set_main_thread_priority(u8 priority) { main_thread_priority_ = priority; }
|
||||||
|
|
||||||
u8 main_thread_core_number() const { return main_thread_core_number_; }
|
u8 main_thread_cpu_id() const { return main_thread_cpu_id_; }
|
||||||
void set_main_thread_core_number(u8 core_number) { main_thread_core_number_ = core_number; }
|
void set_main_thread_cpu_id(u8 cpu_id) { main_thread_cpu_id_ = cpu_id; }
|
||||||
|
|
||||||
u32 version() const { return le_word(version_); }
|
u32 version() const { return le_word(version_); }
|
||||||
void set_version(u32 version) { version_ = le_word(version); }
|
void set_version(u32 version) { version_ = le_word(version); }
|
||||||
|
@ -174,7 +174,7 @@ namespace nx
|
||||||
InstructionType mInstructionType;
|
InstructionType mInstructionType;
|
||||||
ProcAddrSpaceType mProcAddressSpaceType;
|
ProcAddrSpaceType mProcAddressSpaceType;
|
||||||
u8 mMainThreadPriority;
|
u8 mMainThreadPriority;
|
||||||
u8 mMainThreadCoreNumber;
|
u8 mMainThreadCpuId;
|
||||||
u32 mVersion;
|
u32 mVersion;
|
||||||
u32 mMainThreadStackSize;
|
u32 mMainThreadStackSize;
|
||||||
std::string mName;
|
std::string mName;
|
||||||
|
@ -182,7 +182,6 @@ namespace nx
|
||||||
sSection mAciPos;
|
sSection mAciPos;
|
||||||
sSection mAcidPos;
|
sSection mAcidPos;
|
||||||
|
|
||||||
void clearVariables();
|
|
||||||
void calculateOffsets();
|
void calculateOffsets();
|
||||||
bool isEqual(const NpdmHeader& other) const;
|
bool isEqual(const NpdmHeader& other) const;
|
||||||
void copyFrom(const NpdmHeader& other);
|
void copyFrom(const NpdmHeader& other);
|
||||||
|
|
|
@ -59,7 +59,7 @@ void SacBinary::exportBinary()
|
||||||
|
|
||||||
void SacBinary::importBinary(const u8 * bytes, size_t len)
|
void SacBinary::importBinary(const u8 * bytes, size_t len)
|
||||||
{
|
{
|
||||||
clearVariables();
|
clear();
|
||||||
mBinaryBlob.alloc(len);
|
mBinaryBlob.alloc(len);
|
||||||
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
||||||
|
|
||||||
|
@ -73,7 +73,8 @@ void SacBinary::importBinary(const u8 * bytes, size_t len)
|
||||||
|
|
||||||
void nx::SacBinary::clear()
|
void nx::SacBinary::clear()
|
||||||
{
|
{
|
||||||
clearVariables();
|
mBinaryBlob.clear();
|
||||||
|
mServices.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
const fnd::List<SacEntry>& SacBinary::getServiceList() const
|
const fnd::List<SacEntry>& SacBinary::getServiceList() const
|
||||||
|
@ -86,12 +87,6 @@ void SacBinary::addService(const SacEntry& service)
|
||||||
mServices.addElement(service);
|
mServices.addElement(service);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SacBinary::clearVariables()
|
|
||||||
{
|
|
||||||
mBinaryBlob.clear();
|
|
||||||
mServices.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SacBinary::isEqual(const SacBinary & other) const
|
bool SacBinary::isEqual(const SacBinary & other) const
|
||||||
{
|
{
|
||||||
return mServices == other.mServices;
|
return mServices == other.mServices;
|
||||||
|
|
|
@ -41,7 +41,6 @@ namespace nx
|
||||||
// variables
|
// variables
|
||||||
fnd::List<SacEntry> mServices;
|
fnd::List<SacEntry> mServices;
|
||||||
|
|
||||||
void clearVariables();
|
|
||||||
bool isEqual(const SacBinary& other) const;
|
bool isEqual(const SacBinary& other) const;
|
||||||
void copyFrom(const SacBinary& other);
|
void copyFrom(const SacBinary& other);
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,16 +6,16 @@ nx::ThreadInfoEntry::ThreadInfoEntry() :
|
||||||
mCap(kCapId),
|
mCap(kCapId),
|
||||||
mMinPriority(kDefaultPriority),
|
mMinPriority(kDefaultPriority),
|
||||||
mMaxPriority(kDefaultPriority),
|
mMaxPriority(kDefaultPriority),
|
||||||
mMinCoreNumber(kDefaultCoreNumber),
|
mMinCpuId(kDefaultCpuId),
|
||||||
mMaxCoreNumber(kDefaultCoreNumber)
|
mMaxCpuId(kDefaultCpuId)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
nx::ThreadInfoEntry::ThreadInfoEntry(const KernelCapability & kernel_cap) :
|
nx::ThreadInfoEntry::ThreadInfoEntry(const KernelCapability & kernel_cap) :
|
||||||
mCap(kCapId),
|
mCap(kCapId),
|
||||||
mMinPriority(kDefaultPriority),
|
mMinPriority(kDefaultPriority),
|
||||||
mMaxPriority(kDefaultPriority),
|
mMaxPriority(kDefaultPriority),
|
||||||
mMinCoreNumber(kDefaultCoreNumber),
|
mMinCpuId(kDefaultCpuId),
|
||||||
mMaxCoreNumber(kDefaultCoreNumber)
|
mMaxCpuId(kDefaultCpuId)
|
||||||
{
|
{
|
||||||
setKernelCapability(kernel_cap);
|
setKernelCapability(kernel_cap);
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,13 @@ nx::ThreadInfoEntry::ThreadInfoEntry(u8 min_priority, u8 max_priority, u8 min_co
|
||||||
mCap(kCapId),
|
mCap(kCapId),
|
||||||
mMinPriority(kDefaultPriority),
|
mMinPriority(kDefaultPriority),
|
||||||
mMaxPriority(kDefaultPriority),
|
mMaxPriority(kDefaultPriority),
|
||||||
mMinCoreNumber(kDefaultCoreNumber),
|
mMinCpuId(kDefaultCpuId),
|
||||||
mMaxCoreNumber(kDefaultCoreNumber)
|
mMaxCpuId(kDefaultCpuId)
|
||||||
{
|
{
|
||||||
setMinPriority(min_priority);
|
setMinPriority(min_priority);
|
||||||
setMaxPriority(max_priority);
|
setMaxPriority(max_priority);
|
||||||
setMinCoreNumber(min_core_number);
|
setMinCpuId(min_core_number);
|
||||||
setMaxCoreNumber(max_core_number);
|
setMaxCpuId(max_core_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
const nx::KernelCapability & nx::ThreadInfoEntry::getKernelCapability() const
|
const nx::KernelCapability & nx::ThreadInfoEntry::getKernelCapability() const
|
||||||
|
@ -81,34 +81,34 @@ void nx::ThreadInfoEntry::setMaxPriority(u8 priority)
|
||||||
updateCapField();
|
updateCapField();
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 nx::ThreadInfoEntry::getMinCoreNumber() const
|
u8 nx::ThreadInfoEntry::getMinCpuId() const
|
||||||
{
|
{
|
||||||
return mMinCoreNumber;
|
return mMinCpuId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::ThreadInfoEntry::setMinCoreNumber(u8 core_num)
|
void nx::ThreadInfoEntry::setMinCpuId(u8 core_num)
|
||||||
{
|
{
|
||||||
if (core_num > kMaxVal)
|
if (core_num > kMaxVal)
|
||||||
{
|
{
|
||||||
throw fnd::Exception(kModuleName, "Illegal MinCoreNumber (range 0-63)");
|
throw fnd::Exception(kModuleName, "Illegal MinCoreNumber (range 0-63)");
|
||||||
}
|
}
|
||||||
|
|
||||||
mMinCoreNumber = core_num;
|
mMinCpuId = core_num;
|
||||||
updateCapField();
|
updateCapField();
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 nx::ThreadInfoEntry::getMaxCoreNumber() const
|
u8 nx::ThreadInfoEntry::getMaxCpuId() const
|
||||||
{
|
{
|
||||||
return mMaxCoreNumber;
|
return mMaxCpuId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::ThreadInfoEntry::setMaxCoreNumber(u8 core_num)
|
void nx::ThreadInfoEntry::setMaxCpuId(u8 core_num)
|
||||||
{
|
{
|
||||||
if (core_num > kMaxVal)
|
if (core_num > kMaxVal)
|
||||||
{
|
{
|
||||||
throw fnd::Exception(kModuleName, "Illegal MaxCoreNumber (range 0-63)");
|
throw fnd::Exception(kModuleName, "Illegal MaxCoreNumber (range 0-63)");
|
||||||
}
|
}
|
||||||
|
|
||||||
mMaxCoreNumber = core_num;
|
mMaxCpuId = core_num;
|
||||||
updateCapField();
|
updateCapField();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace nx
|
||||||
public:
|
public:
|
||||||
ThreadInfoEntry();
|
ThreadInfoEntry();
|
||||||
ThreadInfoEntry(const KernelCapability& kernel_cap);
|
ThreadInfoEntry(const KernelCapability& kernel_cap);
|
||||||
ThreadInfoEntry(u8 min_priority, u8 max_priority, u8 min_core_number, u8 max_core_number);
|
ThreadInfoEntry(u8 min_priority, u8 max_priority, u8 min_cpu_id, u8 max_cpu_id);
|
||||||
|
|
||||||
// kernel capability
|
// kernel capability
|
||||||
const KernelCapability& getKernelCapability() const;
|
const KernelCapability& getKernelCapability() const;
|
||||||
|
@ -21,10 +21,10 @@ namespace nx
|
||||||
void setMinPriority(u8 priority);
|
void setMinPriority(u8 priority);
|
||||||
u8 getMaxPriority() const;
|
u8 getMaxPriority() const;
|
||||||
void setMaxPriority(u8 priority);
|
void setMaxPriority(u8 priority);
|
||||||
u8 getMinCoreNumber() const;
|
u8 getMinCpuId() const;
|
||||||
void setMinCoreNumber(u8 core_num);
|
void setMinCpuId(u8 cpu_id);
|
||||||
u8 getMaxCoreNumber() const;
|
u8 getMaxCpuId() const;
|
||||||
void setMaxCoreNumber(u8 core_num);
|
void setMaxCpuId(u8 cpu_id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string kModuleName = "THREAD_INFO_ENTRY";
|
const std::string kModuleName = "THREAD_INFO_ENTRY";
|
||||||
|
@ -32,21 +32,21 @@ namespace nx
|
||||||
static const u8 kValBits = 6;
|
static const u8 kValBits = 6;
|
||||||
static const u8 kMaxVal = BIT(kValBits)-1;
|
static const u8 kMaxVal = BIT(kValBits)-1;
|
||||||
static const u8 kDefaultPriority = 6;
|
static const u8 kDefaultPriority = 6;
|
||||||
static const u8 kDefaultCoreNumber = 8;
|
static const u8 kDefaultCpuId = 8;
|
||||||
|
|
||||||
KernelCapability mCap;
|
KernelCapability mCap;
|
||||||
u8 mMinPriority;
|
u8 mMinPriority;
|
||||||
u8 mMaxPriority;
|
u8 mMaxPriority;
|
||||||
u8 mMinCoreNumber;
|
u8 mMinCpuId;
|
||||||
u8 mMaxCoreNumber;
|
u8 mMaxCpuId;
|
||||||
|
|
||||||
inline void updateCapField()
|
inline void updateCapField()
|
||||||
{
|
{
|
||||||
u32 field = 0;
|
u32 field = 0;
|
||||||
field |= (u32)(mMinPriority & kMaxVal) << (kValBits * 0);
|
field |= (u32)(mMinPriority & kMaxVal) << (kValBits * 0);
|
||||||
field |= (u32)(mMaxPriority & kMaxVal) << (kValBits * 1);
|
field |= (u32)(mMaxPriority & kMaxVal) << (kValBits * 1);
|
||||||
field |= (u32)(mMinCoreNumber & kMaxVal) << (kValBits * 2);
|
field |= (u32)(mMinCpuId & kMaxVal) << (kValBits * 2);
|
||||||
field |= (u32)(mMaxCoreNumber & kMaxVal) << (kValBits * 3);
|
field |= (u32)(mMaxCpuId & kMaxVal) << (kValBits * 3);
|
||||||
mCap.setField(field);
|
mCap.setField(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,8 +55,8 @@ namespace nx
|
||||||
u32 field = mCap.getField();
|
u32 field = mCap.getField();
|
||||||
mMinPriority = (field >> (kValBits * 0)) & kMaxVal;
|
mMinPriority = (field >> (kValBits * 0)) & kMaxVal;
|
||||||
mMaxPriority = (field >> (kValBits * 1)) & kMaxVal;
|
mMaxPriority = (field >> (kValBits * 1)) & kMaxVal;
|
||||||
mMinCoreNumber = (field >> (kValBits * 2)) & kMaxVal;
|
mMinCpuId = (field >> (kValBits * 2)) & kMaxVal;
|
||||||
mMaxCoreNumber = (field >> (kValBits * 3)) & kMaxVal;
|
mMaxCpuId = (field >> (kValBits * 3)) & kMaxVal;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,8 @@ void nx::ThreadInfoHandler::clear()
|
||||||
mIsSet = false;
|
mIsSet = false;
|
||||||
mEntry.setMaxPriority(0);
|
mEntry.setMaxPriority(0);
|
||||||
mEntry.setMinPriority(0);
|
mEntry.setMinPriority(0);
|
||||||
mEntry.setMaxCoreNumber(0);
|
mEntry.setMaxCpuId(0);
|
||||||
mEntry.setMinCoreNumber(0);
|
mEntry.setMinCpuId(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nx::ThreadInfoHandler::isSet() const
|
bool nx::ThreadInfoHandler::isSet() const
|
||||||
|
@ -80,25 +80,25 @@ void nx::ThreadInfoHandler::setMaxPriority(u8 priority)
|
||||||
mIsSet = true;
|
mIsSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 nx::ThreadInfoHandler::getMinCoreNumber() const
|
u8 nx::ThreadInfoHandler::getMinCpuId() const
|
||||||
{
|
{
|
||||||
return mEntry.getMinCoreNumber();
|
return mEntry.getMinCpuId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::ThreadInfoHandler::setMinCoreNumber(u8 core_num)
|
void nx::ThreadInfoHandler::setMinCpuId(u8 core_num)
|
||||||
{
|
{
|
||||||
mEntry.setMinCoreNumber(core_num);
|
mEntry.setMinCpuId(core_num);
|
||||||
mIsSet = true;
|
mIsSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 nx::ThreadInfoHandler::getMaxCoreNumber() const
|
u8 nx::ThreadInfoHandler::getMaxCpuId() const
|
||||||
{
|
{
|
||||||
return mEntry.getMaxCoreNumber();
|
return mEntry.getMaxCpuId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::ThreadInfoHandler::setMaxCoreNumber(u8 core_num)
|
void nx::ThreadInfoHandler::setMaxCpuId(u8 core_num)
|
||||||
{
|
{
|
||||||
mEntry.setMaxCoreNumber(core_num);
|
mEntry.setMaxCpuId(core_num);
|
||||||
mIsSet = true;
|
mIsSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,10 @@ namespace nx
|
||||||
void setMinPriority(u8 priority);
|
void setMinPriority(u8 priority);
|
||||||
u8 getMaxPriority() const;
|
u8 getMaxPriority() const;
|
||||||
void setMaxPriority(u8 priority);
|
void setMaxPriority(u8 priority);
|
||||||
u8 getMinCoreNumber() const;
|
u8 getMinCpuId() const;
|
||||||
void setMinCoreNumber(u8 core_num);
|
void setMinCpuId(u8 core_num);
|
||||||
u8 getMaxCoreNumber() const;
|
u8 getMaxCpuId() const;
|
||||||
void setMaxCoreNumber(u8 core_num);
|
void setMaxCpuId(u8 core_num);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string kModuleName = "THREAD_INFO_HANDLER";
|
const std::string kModuleName = "THREAD_INFO_HANDLER";
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="AciBinary.h" />
|
<ClInclude Include="AciBinary.h" />
|
||||||
|
<ClInclude Include="AcidBinary.h" />
|
||||||
<ClInclude Include="AciHeader.h" />
|
<ClInclude Include="AciHeader.h" />
|
||||||
<ClInclude Include="FacBinary.h" />
|
<ClInclude Include="FacBinary.h" />
|
||||||
<ClInclude Include="FacHeader.h" />
|
<ClInclude Include="FacHeader.h" />
|
||||||
|
@ -39,6 +40,7 @@
|
||||||
<ClInclude Include="MiscFlagsHandler.h" />
|
<ClInclude Include="MiscFlagsHandler.h" />
|
||||||
<ClInclude Include="MiscParamsEntry.h" />
|
<ClInclude Include="MiscParamsEntry.h" />
|
||||||
<ClInclude Include="MiscParamsHandler.h" />
|
<ClInclude Include="MiscParamsHandler.h" />
|
||||||
|
<ClInclude Include="NpdmBinary.h" />
|
||||||
<ClInclude Include="NpdmHeader.h" />
|
<ClInclude Include="NpdmHeader.h" />
|
||||||
<ClInclude Include="NcaHeader.h" />
|
<ClInclude Include="NcaHeader.h" />
|
||||||
<ClInclude Include="NXCrypto.h" />
|
<ClInclude Include="NXCrypto.h" />
|
||||||
|
@ -51,6 +53,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="AciBinary.cpp" />
|
<ClCompile Include="AciBinary.cpp" />
|
||||||
|
<ClCompile Include="AcidBinary.cpp" />
|
||||||
<ClCompile Include="AciHeader.cpp" />
|
<ClCompile Include="AciHeader.cpp" />
|
||||||
<ClCompile Include="FacBinary.cpp" />
|
<ClCompile Include="FacBinary.cpp" />
|
||||||
<ClCompile Include="FacHeader.cpp" />
|
<ClCompile Include="FacHeader.cpp" />
|
||||||
|
@ -68,6 +71,7 @@
|
||||||
<ClCompile Include="MiscFlagsHandler.cpp" />
|
<ClCompile Include="MiscFlagsHandler.cpp" />
|
||||||
<ClCompile Include="MiscParamsEntry.cpp" />
|
<ClCompile Include="MiscParamsEntry.cpp" />
|
||||||
<ClCompile Include="MiscParamsHandler.cpp" />
|
<ClCompile Include="MiscParamsHandler.cpp" />
|
||||||
|
<ClCompile Include="NpdmBinary.cpp" />
|
||||||
<ClCompile Include="NpdmHeader.cpp" />
|
<ClCompile Include="NpdmHeader.cpp" />
|
||||||
<ClCompile Include="NcaHeader.cpp" />
|
<ClCompile Include="NcaHeader.cpp" />
|
||||||
<ClCompile Include="SacBinary.cpp" />
|
<ClCompile Include="SacBinary.cpp" />
|
||||||
|
|
|
@ -33,9 +33,6 @@
|
||||||
<ClInclude Include="FacHeader.h">
|
<ClInclude Include="FacHeader.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="FacBinary.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="SacBinary.h">
|
<ClInclude Include="SacBinary.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -102,6 +99,15 @@
|
||||||
<ClInclude Include="KcBinary.h">
|
<ClInclude Include="KcBinary.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="AcidBinary.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="FacBinary.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="NpdmBinary.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="NcaHeader.cpp">
|
<ClCompile Include="NcaHeader.cpp">
|
||||||
|
@ -116,9 +122,6 @@
|
||||||
<ClCompile Include="FacHeader.cpp">
|
<ClCompile Include="FacHeader.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="FacBinary.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="SacBinary.cpp">
|
<ClCompile Include="SacBinary.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -182,5 +185,14 @@
|
||||||
<ClCompile Include="KcBinary.cpp">
|
<ClCompile Include="KcBinary.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="AcidBinary.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="FacBinary.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="NpdmBinary.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in a new issue