[nx] Implemented NpdmBinary and associated child classes.

This commit is contained in:
jakcron 2017-07-17 18:21:39 +10:00
parent 7dd27fd5c8
commit 99151507c6
24 changed files with 768 additions and 354 deletions

View file

@ -3,7 +3,9 @@
nx::AciBinary::AciBinary()
{}
{
clear();
}
nx::AciBinary::AciBinary(const AciBinary & other)
{

View file

@ -2,28 +2,17 @@
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()
{
mFac.offset = align(sizeof(sAciHeader), kAciAlignSize);
mFac.offset = align(mHeaderOffset, kAciAlignSize) + align(sizeof(sAciHeader), kAciAlignSize);
mSac.offset = mFac.offset + align(mFac.size, kAciAlignSize);
mKc.offset = mSac.offset + align(mSac.size, kAciAlignSize);
}
bool AciHeader::isEqual(const AciHeader & other) const
{
return (mType == other.mType) \
return (mHeaderOffset == other.mHeaderOffset) \
&& (mType == other.mType) \
&& (mAcidSize == other.mAcidSize) \
&& (mProgramId == other.mProgramId) \
&& (mFac == other.mFac) \
@ -39,6 +28,7 @@ void AciHeader::copyFrom(const AciHeader & other)
}
else
{
mHeaderOffset = other.mHeaderOffset;
mType = other.mType;
mAcidSize = other.mAcidSize;
mProgramId = other.mProgramId;
@ -50,7 +40,7 @@ void AciHeader::copyFrom(const AciHeader & other)
AciHeader::AciHeader()
{
clearVariables();
clear();
}
AciHeader::AciHeader(const AciHeader & other)
@ -106,17 +96,36 @@ void AciHeader::exportBinary()
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)
{
// set program
hdr->set_program_id(mProgramId);
switch (mFormatVersion)
{
case(0):
break;
default:
throw fnd::Exception(kModuleName, "Unsupported ACI0 version");
}
}
else if (mType == TYPE_ACID)
{
hdr->set_version(mAcidVersion);
switch (mAcidVersion)
switch (mFormatVersion)
{
case(0):
mAcidSize = getAciSize();
hdr->set_size(mAcidSize);
hdr->set_program_id_min(0);
hdr->set_program_id_max(0);
@ -130,16 +139,6 @@ void AciHeader::exportBinary()
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)
@ -149,7 +148,7 @@ void AciHeader::importBinary(const u8 * bytes, size_t len)
throw fnd::Exception(kModuleName, "ACI header too small");
}
clearVariables();
clear();
mBinaryBlob.alloc(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)
{
mProgramId = hdr->program_id();
mAcidVersion = 0;
mFormatVersion = hdr->version();
mAcidSize = 0;
mProgramIdMin = 0;
mProgramIdMax = 0;
switch (mFormatVersion)
{
case(0):
break;
default:
throw fnd::Exception(kModuleName, "Unsupported ACI0 version");
}
}
else if (mType == TYPE_ACID)
{
mProgramId = 0;
mAcidVersion = hdr->version();
switch (mAcidVersion)
mFormatVersion = hdr->version();
switch (mFormatVersion)
{
case(0):
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();
mSac.offset = hdr->sac().offset();
mSac.offset = hdr->sac().offset() - mHeaderOffset;
mSac.size = hdr->sac().size();
mKc.offset = hdr->kc().offset();
mKc.offset = hdr->kc().offset() - mHeaderOffset;
mKc.size = hdr->kc().size();
}
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
@ -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));
}
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
@ -232,10 +250,12 @@ size_t nx::AciHeader::getAcidSize() const
return mAcidSize;
}
/*
void nx::AciHeader::setAcidSize(size_t size)
{
mAcidSize = size;
}
*/
u64 nx::AciHeader::getProgramIdMin() const
{
@ -257,6 +277,11 @@ void nx::AciHeader::setProgramIdMax(u64 program_id)
mProgramIdMax = program_id;
}
void nx::AciHeader::setHeaderOffset(size_t offset)
{
mHeaderOffset = offset;
}
AciHeader::AciType AciHeader::getAciType() const
{
return mType;
@ -282,7 +307,7 @@ const AciHeader::sSection & AciHeader::getFacPos() const
return mFac;
}
void AciHeader::setFacSize(u32 size)
void AciHeader::setFacSize(size_t size)
{
mFac.size = size;
}
@ -292,7 +317,7 @@ const AciHeader::sSection & AciHeader::getSacPos() const
return mSac;
}
void AciHeader::setSacSize(u32 size)
void AciHeader::setSacSize(size_t size)
{
mSac.size = size;
}
@ -302,7 +327,7 @@ const AciHeader::sSection & AciHeader::getKcPos() const
return mKc;
}
void AciHeader::setKcSize(u32 size)
void AciHeader::setKcSize(size_t size)
{
mKc.size = size;
}

View file

@ -63,24 +63,25 @@ namespace nx
void setProgramId(u64 program_id);
// ACID only
u32 getAcidVersion() const;
void setAcidVersion(u32 version);
size_t getAcidSize() const;
void setAcidSize(size_t size);
//void setAcidSize(size_t size);
u64 getProgramIdMin() const;
void setProgramIdMin(u64 program_id);
u64 getProgramIdMax() const;
void setProgramIdMax(u64 program_id);
// ACID & ACI0
void setHeaderOffset(size_t offset);
AciType getAciType() const;
void setAciType(AciType type);
u32 getFormatVersion() const;
void setFormatVersion(u32 version);
const sSection& getFacPos() const;
void setFacSize(u32 size);
void setFacSize(size_t size);
const sSection& getSacPos() const;
void setSacSize(u32 size);
void setSacSize(size_t size);
const sSection& getKcPos() const;
void setKcSize(u32 size);
void setKcSize(size_t size);
private:
const std::string kModuleName = "ACI_HEADER";
@ -94,8 +95,8 @@ namespace nx
private:
u8 signature_[4];
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
u8 reserved_1[4];
u64 program_id_; // set only in ACI0 (since ACID is generic)
u64 program_id_max_;
struct sAciSection
@ -109,7 +110,7 @@ namespace nx
u32 size() const { return le_word(size_); }
void set_size(u32 size) { size_ = le_word(size); }
} fac_, sac_, kc_, reserved_3;
} fac_, sac_, kc_;
public:
const char* signature() const { return (const char*)signature_; }
void set_signature(const char* signature) { memcpy(signature_, signature, 4); }
@ -147,16 +148,15 @@ namespace nx
u64 mProgramId;
// ACID variables
u32 mAcidVersion;
size_t mAcidSize;
u64 mProgramIdMin;
u64 mProgramIdMax;
// ACI(D) variables
size_t mHeaderOffset;
AciType mType;
u32 mFormatVersion;
sSection mFac, mSac, mKc;
void clearVariables();
void calculateSectionOffsets();
bool isEqual(const AciHeader& other) const;
void copyFrom(const AciHeader& other);

142
lib/nx/AcidBinary.cpp Normal file
View 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
View 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);
};
}

View file

@ -1,156 +1,102 @@
#include "FacBinary.h"
using namespace nx;
FacBinary::FacBinary() :
mHeader()
{
clearVariables();
}
FacBinary::FacBinary(const FacBinary & other)
{
importBinary(other.getBytes(), other.getSize());
}
nx::FacBinary::FacBinary()
{}
FacBinary::FacBinary(const u8 * bytes, size_t len)
{
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)
nx::FacBinary::FacBinary(const FacBinary & 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();
}
size_t FacBinary::getSize() const
size_t nx::FacBinary::getSize() const
{
return mBinaryBlob.getSize();
}
void FacBinary::exportBinary()
void nx::FacBinary::exportBinary()
{
mHeader.setFsaRights(mFsaRights);
mHeader.setContentOwnerIdSize(mContentOwnerIds.getSize() * sizeof(u32));
mHeader.setSaveDataOwnerIdSize(mSaveDataOwnerIds.getSize() * sizeof(u32));
mHeader.exportBinary();
FacHeader::setContentOwnerIdSize(mContentOwnerIdList.getSize() * sizeof(u32));
FacHeader::setSaveDataOwnerIdSize(mSaveDataOwnerIdList.getSize() * sizeof(u32));
FacHeader::exportBinary();
mBinaryBlob.alloc(mHeader.getFacSize());
memcpy(mBinaryBlob.getBytes(), mHeader.getBytes(), mHeader.getSize());
mBinaryBlob.alloc(getFacSize());
memcpy(mBinaryBlob.getBytes(), FacHeader::getBytes(), FacHeader::getSize());
u32* rawContentOwnerIds = (u32*)(mBinaryBlob.getBytes() + mHeader.getContentOwnerIdOffset());
for (size_t i = 0; i < mContentOwnerIds.getSize(); i++)
u32* rawContentOwnerIds = (u32*)(mBinaryBlob.getBytes() + FacHeader::getContentOwnerIdOffset());
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());
for (size_t i = 0; i < mSaveDataOwnerIds.getSize(); i++)
u32* rawSaveDataOwnerIds = (u32*)(mBinaryBlob.getBytes() + FacHeader::getSaveDataOwnerIdOffset());
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();
mHeader.importBinary(bytes, len);
if (mHeader.getFacSize() > len)
clear();
FacHeader::importBinary(bytes, len);
if (FacHeader::getFacSize() > len)
{
throw fnd::Exception(kModuleName, "FAC binary too small");
}
mBinaryBlob.alloc(mHeader.getFacSize());
mBinaryBlob.alloc(FacHeader::getFacSize());
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
mFsaRights = mHeader.getFsaRights();
u32* rawContentOwnerIds = (u32*)(mBinaryBlob.getBytes() + mHeader.getContentOwnerIdOffset());
size_t rawContentOwnerIdNum = mHeader.getContentOwnerIdSize() / sizeof(u32);
u32* rawContentOwnerIds = (u32*)(mBinaryBlob.getBytes() + FacHeader::getContentOwnerIdOffset());
size_t rawContentOwnerIdNum = FacHeader::getContentOwnerIdSize() / sizeof(u32);
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());
size_t rawSaveDataOwnerIdNum = mHeader.getSaveDataOwnerIdSize() / sizeof(u32);
u32* rawSaveDataOwnerIds = (u32*)(mBinaryBlob.getBytes() + FacHeader::getSaveDataOwnerIdOffset());
size_t rawSaveDataOwnerIdNum = FacHeader::getSaveDataOwnerIdSize() / sizeof(u32);
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
{
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)
void nx::FacBinary::copyFrom(const FacBinary & other)
{
if (other.getSize())
{
@ -158,10 +104,35 @@ void FacBinary::copyFrom(const FacBinary & other)
}
else
{
mBinaryBlob.clear();
mHeader = other.mHeader;
mFsaRights = other.mFsaRights;
mContentOwnerIds = other.mContentOwnerIds;
mSaveDataOwnerIds = other.mSaveDataOwnerIds;
FacHeader::operator=(other);
mContentOwnerIdList = other.mContentOwnerIdList;
mSaveDataOwnerIdList = other.mSaveDataOwnerIdList;
}
}
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;
}

View file

@ -5,38 +5,13 @@
#include <nx/ISerialiseableBinary.h>
#include <nx/FacHeader.h>
namespace nx
{
class FacBinary :
public ISerialiseableBinary
public FacHeader
{
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(const FacBinary& other);
FacBinary(const u8* bytes, size_t len);
@ -55,28 +30,24 @@ namespace nx
// variables
void clear();
bool isPermissionSet(FsAccessFlag flag) const;
void addPermission(FsAccessFlag flag);
void removePermission(FsAccessFlag flag);
const fnd::List<u32>& getContentOwnerIds() const;
void addContentOwnerId(u32 id);
const fnd::List<u32>& getContentOwnerIdList() const;
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:
const std::string kModuleName = "FAC_BINARY";
static const u32 kFacFormatVersion = 1;
// raw binary
fnd::MemoryBlob mBinaryBlob;
// variables
FacHeader mHeader;
u64 mFsaRights;
fnd::List<u32> mContentOwnerIds;
fnd::List<u32> mSaveDataOwnerIds;
fnd::List<u32> mContentOwnerIdList;
fnd::List<u32> mSaveDataOwnerIdList;
void clearVariables();
bool isEqual(const FacBinary& other) const;
void copyFrom(const FacBinary& other);
};

View file

@ -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);
}
nx::FacHeader::FacHeader(const u8 * bytes, size_t len)
nx::FacHeader::FacHeader(const u8 * bytes, size_t len) :
mFsaRights()
{
importBinary(bytes, len);
}
@ -47,8 +50,18 @@ void nx::FacHeader::exportBinary()
mBinaryBlob.alloc(sizeof(sFacHeader));
sFacHeader* hdr = (sFacHeader*)mBinaryBlob.getBytes();
hdr->set_version(kFacFormatVersion);
hdr->set_fac_flags(mFsaRights);
if (mVersion != kFacFormatVersion)
{
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();
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");
}
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.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();
@ -82,7 +103,11 @@ void nx::FacHeader::importBinary(const u8 * bytes, size_t len)
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
@ -92,14 +117,28 @@ size_t nx::FacHeader::getFacSize() const
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;
}
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
@ -132,15 +171,6 @@ void nx::FacHeader::setSaveDataOwnerIdSize(size_t 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()
{
mContentOwnerIdPos.offset = align(sizeof(sFacHeader), 4);

View file

@ -1,6 +1,7 @@
#pragma once
#include <string>
#include <fnd/memory_blob.h>
#include <fnd/List.h>
#include <nx/ISerialiseableBinary.h>
namespace nx
@ -9,6 +10,32 @@ namespace nx
public ISerialiseableBinary
{
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(const FacHeader& other);
FacHeader(const u8* bytes, size_t len);
@ -29,8 +56,11 @@ namespace nx
void clear();
size_t getFacSize() const;
u64 getFsaRights() const;
void setFsaRights(u64 flag);
u32 getFormatVersion() const;
void setFormatVersion(u32 version);
const fnd::List<FsAccessFlag>& getFsaRightsList() const;
void setFsaRightsList(const fnd::List<FsAccessFlag>& list);
size_t getContentOwnerIdOffset() const;
size_t getContentOwnerIdSize() const;
@ -81,14 +111,14 @@ namespace nx
fnd::MemoryBlob mBinaryBlob;
// variables
u64 mFsaRights;
u32 mVersion;
fnd::List<FsAccessFlag> mFsaRights;
struct sSection
{
size_t offset;
size_t size;
} mContentOwnerIdPos, mSaveDataOwnerIdPos;
void clearVariables();
void calculateOffsets();
bool isEqual(const FacHeader& other) const;
void copyFrom(const FacHeader& other);

View file

@ -131,7 +131,15 @@ void nx::KcBinary::importBinary(const u8 * bytes, size_t len)
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
@ -214,19 +222,6 @@ nx::MiscFlagsHandler & nx::KcBinary::getMiscFlags()
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
{
return (mThreadInfo == other.mThreadInfo) \

View file

@ -41,7 +41,7 @@ void NcaHeader::importBinary(const u8 * bytes, size_t len)
throw fnd::Exception(kModuleName, "NCA header size is too small");
}
clearVariables();
clear();
mBinaryBlob.alloc(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()
{
clearVariables();
mBlockSize = 0;
mNcaSize = 0;
mProgramId = 0;
mUnk0 = 0;
mSections.clear();
mAesKeys.clear();
}
u64 NcaHeader::getNcaSize() const
@ -135,16 +140,6 @@ void NcaHeader::addKey(const crypto::aes::sAes128Key & 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
{
return block_num*mBlockSize;
@ -185,7 +180,7 @@ void NcaHeader::copyFrom(const NcaHeader & other)
NcaHeader::NcaHeader()
{
clearVariables();
clear();
}
NcaHeader::NcaHeader(const NcaHeader & other)

View file

@ -149,7 +149,6 @@ namespace nx
fnd::List<sSection> mSections;
fnd::List<crypto::aes::sAes128Key> mAesKeys;
void clearVariables();
u64 blockNumToSize(u32 block_num) const;
u32 sizeToBlockNum(u64 real_size) const;
bool isEqual(const NcaHeader& other) const;

136
lib/nx/NpdmBinary.cpp Normal file
View 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
View 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);
};
}

View file

@ -4,7 +4,7 @@
nx::NpdmHeader::NpdmHeader()
{
clearVariables();
clear();
}
nx::NpdmHeader::NpdmHeader(const NpdmHeader & other)
@ -42,23 +42,6 @@ size_t nx::NpdmHeader::getSize() const
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()
{
mAcidPos.offset = align(sizeof(sNpdmHeader), kNpdmAlignSize);
@ -70,7 +53,7 @@ bool nx::NpdmHeader::isEqual(const NpdmHeader & other) const
return (mInstructionType == other.mInstructionType) \
&& (mProcAddressSpaceType == other.mProcAddressSpaceType) \
&& (mMainThreadPriority == other.mMainThreadPriority) \
&& (mMainThreadCoreNumber == other.mMainThreadCoreNumber) \
&& (mMainThreadCpuId == other.mMainThreadCpuId) \
&& (mVersion == other.mVersion) \
&& (mMainThreadStackSize == other.mMainThreadStackSize) \
&& (mName == other.mName) \
@ -90,7 +73,7 @@ void nx::NpdmHeader::copyFrom(const NpdmHeader & other)
mInstructionType = other.mInstructionType;
mProcAddressSpaceType = other.mProcAddressSpaceType;
mMainThreadPriority = other.mMainThreadPriority;
mMainThreadCoreNumber = other.mMainThreadCoreNumber;
mMainThreadCpuId = other.mMainThreadCpuId;
mVersion = other.mVersion;
mMainThreadStackSize = other.mMainThreadStackSize;
mName = other.mName;
@ -109,7 +92,7 @@ void nx::NpdmHeader::exportBinary()
u8 flag = ((u8)(mInstructionType & 1) | (u8)((mProcAddressSpaceType & 3) << 1)) & 0xf;
hdr->set_flags(flag);
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_main_thread_stack_size(mMainThreadStackSize);
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");
}
clearVariables();
clear();
mBinaryBlob.alloc(sizeof(sNpdmHeader));
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
@ -144,11 +127,19 @@ void nx::NpdmHeader::importBinary(const u8 * bytes, size_t len)
mInstructionType = (InstructionType)(flag & 1);
mProcAddressSpaceType = (ProcAddrSpaceType)((flag >> 1) & 3);
mMainThreadPriority = hdr->main_thread_priority();
mMainThreadCoreNumber = hdr->main_thread_core_number();
mMainThreadCpuId = hdr->main_thread_cpu_id();
mVersion = hdr->version();
mMainThreadStackSize = hdr->main_thread_stack_size();
mName = std::string(hdr->name(), kNameMaxLen);
if (mName[0] == '\0')
{
mName.clear();
}
mProductCode = std::string(hdr->product_code(), kProductCodeMaxLen);
if (mProductCode[0] == '\0')
{
mProductCode.clear();
}
mAciPos.offset = hdr->aci().offset();
mAciPos.size = hdr->aci().size();
mAcidPos.offset = hdr->acid().offset();
@ -157,7 +148,19 @@ void nx::NpdmHeader::importBinary(const u8 * bytes, size_t len)
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
@ -200,14 +203,14 @@ void nx::NpdmHeader::setMainThreadPriority(u8 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
@ -265,7 +268,7 @@ const nx::NpdmHeader::sSection & nx::NpdmHeader::getAciPos() const
return mAciPos;
}
void nx::NpdmHeader::setSetAciSize(size_t size)
void nx::NpdmHeader::setAciSize(size_t size)
{
mAciPos.size = size;
}
@ -275,7 +278,7 @@ const nx::NpdmHeader::sSection & nx::NpdmHeader::getAcidPos() const
return mAcidPos;
}
void nx::NpdmHeader::setSetAcidSize(size_t size)
void nx::NpdmHeader::setAcidSize(size_t size)
{
mAcidPos.size = size;
}

View file

@ -76,8 +76,8 @@ namespace nx
u8 getMainThreadPriority() const;
void setMainThreadPriority(u8 priority);
u8 getMainThreadCoreNumber() const;
void setMainThreadCoreNumber(u8 core_num);
u8 getMainThreadCpuId() const;
void setMainThreadCpuId(u8 cpu_id);
u32 getVersion() const;
void setVersion(u32 version);
@ -92,10 +92,10 @@ namespace nx
void setProductCode(const std::string& product_code);
const sSection& getAciPos() const;
void setSetAciSize(size_t size);
void setAciSize(size_t size);
const sSection& getAcidPos() const;
void setSetAcidSize(size_t size);
void setAcidSize(size_t size);
private:
const std::string kModuleName = "NPDM_HEADER";
const std::string kNpdmStructSig = "META";
@ -114,7 +114,7 @@ namespace nx
u8 flags_;
u8 reserved_1;
u8 main_thread_priority_; // 0-63 inclusive
u8 main_thread_core_number_;
u8 main_thread_cpu_id_;
u8 reserved_2[8];
u32 version_;
u32 main_thread_stack_size_; // default 4096
@ -144,8 +144,8 @@ namespace nx
u8 main_thread_priority() const { return main_thread_priority_; }
void set_main_thread_priority(u8 priority) { main_thread_priority_ = priority; }
u8 main_thread_core_number() const { return main_thread_core_number_; }
void set_main_thread_core_number(u8 core_number) { main_thread_core_number_ = core_number; }
u8 main_thread_cpu_id() const { return main_thread_cpu_id_; }
void set_main_thread_cpu_id(u8 cpu_id) { main_thread_cpu_id_ = cpu_id; }
u32 version() const { return le_word(version_); }
void set_version(u32 version) { version_ = le_word(version); }
@ -174,7 +174,7 @@ namespace nx
InstructionType mInstructionType;
ProcAddrSpaceType mProcAddressSpaceType;
u8 mMainThreadPriority;
u8 mMainThreadCoreNumber;
u8 mMainThreadCpuId;
u32 mVersion;
u32 mMainThreadStackSize;
std::string mName;
@ -182,7 +182,6 @@ namespace nx
sSection mAciPos;
sSection mAcidPos;
void clearVariables();
void calculateOffsets();
bool isEqual(const NpdmHeader& other) const;
void copyFrom(const NpdmHeader& other);

View file

@ -59,7 +59,7 @@ void SacBinary::exportBinary()
void SacBinary::importBinary(const u8 * bytes, size_t len)
{
clearVariables();
clear();
mBinaryBlob.alloc(len);
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
@ -73,7 +73,8 @@ void SacBinary::importBinary(const u8 * bytes, size_t len)
void nx::SacBinary::clear()
{
clearVariables();
mBinaryBlob.clear();
mServices.clear();
}
const fnd::List<SacEntry>& SacBinary::getServiceList() const
@ -86,12 +87,6 @@ void SacBinary::addService(const SacEntry& service)
mServices.addElement(service);
}
void SacBinary::clearVariables()
{
mBinaryBlob.clear();
mServices.clear();
}
bool SacBinary::isEqual(const SacBinary & other) const
{
return mServices == other.mServices;

View file

@ -41,7 +41,6 @@ namespace nx
// variables
fnd::List<SacEntry> mServices;
void clearVariables();
bool isEqual(const SacBinary& other) const;
void copyFrom(const SacBinary& other);
};

View file

@ -6,16 +6,16 @@ nx::ThreadInfoEntry::ThreadInfoEntry() :
mCap(kCapId),
mMinPriority(kDefaultPriority),
mMaxPriority(kDefaultPriority),
mMinCoreNumber(kDefaultCoreNumber),
mMaxCoreNumber(kDefaultCoreNumber)
mMinCpuId(kDefaultCpuId),
mMaxCpuId(kDefaultCpuId)
{}
nx::ThreadInfoEntry::ThreadInfoEntry(const KernelCapability & kernel_cap) :
mCap(kCapId),
mMinPriority(kDefaultPriority),
mMaxPriority(kDefaultPriority),
mMinCoreNumber(kDefaultCoreNumber),
mMaxCoreNumber(kDefaultCoreNumber)
mMinCpuId(kDefaultCpuId),
mMaxCpuId(kDefaultCpuId)
{
setKernelCapability(kernel_cap);
}
@ -24,13 +24,13 @@ nx::ThreadInfoEntry::ThreadInfoEntry(u8 min_priority, u8 max_priority, u8 min_co
mCap(kCapId),
mMinPriority(kDefaultPriority),
mMaxPriority(kDefaultPriority),
mMinCoreNumber(kDefaultCoreNumber),
mMaxCoreNumber(kDefaultCoreNumber)
mMinCpuId(kDefaultCpuId),
mMaxCpuId(kDefaultCpuId)
{
setMinPriority(min_priority);
setMaxPriority(max_priority);
setMinCoreNumber(min_core_number);
setMaxCoreNumber(max_core_number);
setMinCpuId(min_core_number);
setMaxCpuId(max_core_number);
}
const nx::KernelCapability & nx::ThreadInfoEntry::getKernelCapability() const
@ -81,34 +81,34 @@ void nx::ThreadInfoEntry::setMaxPriority(u8 priority)
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)
{
throw fnd::Exception(kModuleName, "Illegal MinCoreNumber (range 0-63)");
}
mMinCoreNumber = core_num;
mMinCpuId = core_num;
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)
{
throw fnd::Exception(kModuleName, "Illegal MaxCoreNumber (range 0-63)");
}
mMaxCoreNumber = core_num;
mMaxCpuId = core_num;
updateCapField();
}

View file

@ -10,7 +10,7 @@ namespace nx
public:
ThreadInfoEntry();
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
const KernelCapability& getKernelCapability() const;
@ -21,10 +21,10 @@ namespace nx
void setMinPriority(u8 priority);
u8 getMaxPriority() const;
void setMaxPriority(u8 priority);
u8 getMinCoreNumber() const;
void setMinCoreNumber(u8 core_num);
u8 getMaxCoreNumber() const;
void setMaxCoreNumber(u8 core_num);
u8 getMinCpuId() const;
void setMinCpuId(u8 cpu_id);
u8 getMaxCpuId() const;
void setMaxCpuId(u8 cpu_id);
private:
const std::string kModuleName = "THREAD_INFO_ENTRY";
@ -32,21 +32,21 @@ namespace nx
static const u8 kValBits = 6;
static const u8 kMaxVal = BIT(kValBits)-1;
static const u8 kDefaultPriority = 6;
static const u8 kDefaultCoreNumber = 8;
static const u8 kDefaultCpuId = 8;
KernelCapability mCap;
u8 mMinPriority;
u8 mMaxPriority;
u8 mMinCoreNumber;
u8 mMaxCoreNumber;
u8 mMinCpuId;
u8 mMaxCpuId;
inline void updateCapField()
{
u32 field = 0;
field |= (u32)(mMinPriority & kMaxVal) << (kValBits * 0);
field |= (u32)(mMaxPriority & kMaxVal) << (kValBits * 1);
field |= (u32)(mMinCoreNumber & kMaxVal) << (kValBits * 2);
field |= (u32)(mMaxCoreNumber & kMaxVal) << (kValBits * 3);
field |= (u32)(mMinCpuId & kMaxVal) << (kValBits * 2);
field |= (u32)(mMaxCpuId & kMaxVal) << (kValBits * 3);
mCap.setField(field);
}
@ -55,8 +55,8 @@ namespace nx
u32 field = mCap.getField();
mMinPriority = (field >> (kValBits * 0)) & kMaxVal;
mMaxPriority = (field >> (kValBits * 1)) & kMaxVal;
mMinCoreNumber = (field >> (kValBits * 2)) & kMaxVal;
mMaxCoreNumber = (field >> (kValBits * 3)) & kMaxVal;
mMinCpuId = (field >> (kValBits * 2)) & kMaxVal;
mMaxCpuId = (field >> (kValBits * 3)) & kMaxVal;
}
};
}

View file

@ -49,8 +49,8 @@ void nx::ThreadInfoHandler::clear()
mIsSet = false;
mEntry.setMaxPriority(0);
mEntry.setMinPriority(0);
mEntry.setMaxCoreNumber(0);
mEntry.setMinCoreNumber(0);
mEntry.setMaxCpuId(0);
mEntry.setMinCpuId(0);
}
bool nx::ThreadInfoHandler::isSet() const
@ -80,25 +80,25 @@ void nx::ThreadInfoHandler::setMaxPriority(u8 priority)
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;
}
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;
}

View file

@ -25,10 +25,10 @@ namespace nx
void setMinPriority(u8 priority);
u8 getMaxPriority() const;
void setMaxPriority(u8 priority);
u8 getMinCoreNumber() const;
void setMinCoreNumber(u8 core_num);
u8 getMaxCoreNumber() const;
void setMaxCoreNumber(u8 core_num);
u8 getMinCpuId() const;
void setMinCpuId(u8 core_num);
u8 getMaxCpuId() const;
void setMaxCpuId(u8 core_num);
private:
const std::string kModuleName = "THREAD_INFO_HANDLER";

View file

@ -20,6 +20,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="AciBinary.h" />
<ClInclude Include="AcidBinary.h" />
<ClInclude Include="AciHeader.h" />
<ClInclude Include="FacBinary.h" />
<ClInclude Include="FacHeader.h" />
@ -39,6 +40,7 @@
<ClInclude Include="MiscFlagsHandler.h" />
<ClInclude Include="MiscParamsEntry.h" />
<ClInclude Include="MiscParamsHandler.h" />
<ClInclude Include="NpdmBinary.h" />
<ClInclude Include="NpdmHeader.h" />
<ClInclude Include="NcaHeader.h" />
<ClInclude Include="NXCrypto.h" />
@ -51,6 +53,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="AciBinary.cpp" />
<ClCompile Include="AcidBinary.cpp" />
<ClCompile Include="AciHeader.cpp" />
<ClCompile Include="FacBinary.cpp" />
<ClCompile Include="FacHeader.cpp" />
@ -68,6 +71,7 @@
<ClCompile Include="MiscFlagsHandler.cpp" />
<ClCompile Include="MiscParamsEntry.cpp" />
<ClCompile Include="MiscParamsHandler.cpp" />
<ClCompile Include="NpdmBinary.cpp" />
<ClCompile Include="NpdmHeader.cpp" />
<ClCompile Include="NcaHeader.cpp" />
<ClCompile Include="SacBinary.cpp" />

View file

@ -33,9 +33,6 @@
<ClInclude Include="FacHeader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FacBinary.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SacBinary.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -102,6 +99,15 @@
<ClInclude Include="KcBinary.h">
<Filter>Header Files</Filter>
</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>
<ClCompile Include="NcaHeader.cpp">
@ -116,9 +122,6 @@
<ClCompile Include="FacHeader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FacBinary.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SacBinary.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -182,5 +185,14 @@
<ClCompile Include="KcBinary.cpp">
<Filter>Source Files</Filter>
</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>
</Project>