mirror of
https://github.com/jakcron/nstool.git
synced 2024-12-22 18:55:29 +00:00
Merge pull request #8 from jakcron/npdm-development
[nx|nstool] Updated npdm->aci flag information. Also corrected some bugs
This commit is contained in:
commit
2b11b434b6
|
@ -78,6 +78,8 @@ namespace nx
|
||||||
void setAciType(AciType type);
|
void setAciType(AciType type);
|
||||||
bool isProduction() const;
|
bool isProduction() const;
|
||||||
void setIsProduction(bool isProduction);
|
void setIsProduction(bool isProduction);
|
||||||
|
bool isUnqualifiedApproval() const;
|
||||||
|
void setIsUnqualifiedApproval(bool isUnqualifiedApproval);
|
||||||
const sSection& getFacPos() const;
|
const sSection& getFacPos() const;
|
||||||
void setFacSize(size_t size);
|
void setFacSize(size_t size);
|
||||||
const sSection& getSacPos() const;
|
const sSection& getSacPos() const;
|
||||||
|
@ -103,6 +105,7 @@ namespace nx
|
||||||
size_t mHeaderOffset;
|
size_t mHeaderOffset;
|
||||||
AciType mType;
|
AciType mType;
|
||||||
bool mIsProduction;
|
bool mIsProduction;
|
||||||
|
bool mIsUnqualifiedApproval;
|
||||||
sSection mFac, mSac, mKc;
|
sSection mFac, mSac, mKc;
|
||||||
|
|
||||||
void calculateSectionOffsets();
|
void calculateSectionOffsets();
|
||||||
|
|
|
@ -12,56 +12,34 @@ namespace nx
|
||||||
const std::string kAciStructSig = "ACI0";
|
const std::string kAciStructSig = "ACI0";
|
||||||
const std::string kAciDescStructSig = "ACID";
|
const std::string kAciDescStructSig = "ACID";
|
||||||
static const size_t kAciAlignSize = 0x10;
|
static const size_t kAciAlignSize = 0x10;
|
||||||
|
|
||||||
|
enum Flags
|
||||||
|
{
|
||||||
|
FLAG_PRODUCTION,
|
||||||
|
FLAG_UNQUALIFIED_APPROVAL
|
||||||
|
};
|
||||||
}
|
}
|
||||||
#pragma pack(push,1)
|
#pragma pack(push,1)
|
||||||
struct sAciHeader
|
struct sAciHeader
|
||||||
{
|
{
|
||||||
private:
|
char signature[4];
|
||||||
byte_t signature_[4];
|
le_uint32_t size; // includes prefacing signature, set only in ACID made by SDK (it enables easy resigning)
|
||||||
uint32_t size_; // includes prefacing signature, set only in ACID made by SDK (it enables easy resigning)
|
|
||||||
byte_t reserved_0[4];
|
byte_t reserved_0[4];
|
||||||
uint32_t flags_; // set in ACID only
|
le_uint32_t flags; // set in ACID only
|
||||||
uint64_t program_id_; // set only in ACI0 (since ACID is generic)
|
union uProgramIdInfo
|
||||||
uint64_t program_id_max_;
|
{
|
||||||
|
struct sRestrictProgramId
|
||||||
|
{
|
||||||
|
le_uint64_t min;
|
||||||
|
le_uint64_t max;
|
||||||
|
} program_id_restrict;
|
||||||
|
le_uint64_t program_id;
|
||||||
|
} program_id_info;
|
||||||
struct sAciSection
|
struct sAciSection
|
||||||
{
|
{
|
||||||
private:
|
le_uint32_t offset; // aligned by 0x10 from the last one
|
||||||
uint32_t offset_; // aligned by 0x10 from the last one
|
le_uint32_t size;
|
||||||
uint32_t size_;
|
} fac, sac, kc;
|
||||||
public:
|
|
||||||
uint32_t offset() const { return le_word(offset_); }
|
|
||||||
void set_offset(uint32_t offset) { offset_ = le_word(offset); }
|
|
||||||
|
|
||||||
uint32_t size() const { return le_word(size_); }
|
|
||||||
void set_size(uint32_t size) { size_ = le_word(size); }
|
|
||||||
} fac_, sac_, kc_;
|
|
||||||
public:
|
|
||||||
const char* signature() const { return (const char*)signature_; }
|
|
||||||
void set_signature(const char* signature) { memcpy(signature_, signature, 4); }
|
|
||||||
|
|
||||||
uint32_t size() const { return le_word(size_); }
|
|
||||||
void set_size(uint32_t size) { size_ = le_word(size); }
|
|
||||||
|
|
||||||
uint32_t flags() const { return le_word(flags_); }
|
|
||||||
void set_flags(uint32_t flags) { flags_ = le_word(flags); }
|
|
||||||
|
|
||||||
uint64_t program_id() const { return le_dword(program_id_); }
|
|
||||||
void set_program_id(uint64_t program_id) { program_id_ = le_dword(program_id); }
|
|
||||||
|
|
||||||
uint64_t program_id_min() const { return program_id(); }
|
|
||||||
void set_program_id_min(uint64_t program_id) { set_program_id(program_id); }
|
|
||||||
|
|
||||||
uint64_t program_id_max() const { return le_dword(program_id_max_); }
|
|
||||||
void set_program_id_max(uint64_t program_id) { program_id_max_ = le_dword(program_id); }
|
|
||||||
|
|
||||||
const sAciSection& fac() const { return fac_; }
|
|
||||||
sAciSection& fac() { return fac_; }
|
|
||||||
|
|
||||||
const sAciSection& sac() const { return sac_; }
|
|
||||||
sAciSection& sac() { return sac_; }
|
|
||||||
|
|
||||||
const sAciSection& kc() const { return kc_; }
|
|
||||||
sAciSection& kc() { return kc_; }
|
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
}
|
}
|
|
@ -13,7 +13,11 @@ bool AciHeader::isEqual(const AciHeader & other) const
|
||||||
{
|
{
|
||||||
return (mHeaderOffset == other.mHeaderOffset) \
|
return (mHeaderOffset == other.mHeaderOffset) \
|
||||||
&& (mType == other.mType) \
|
&& (mType == other.mType) \
|
||||||
|
&& (mIsProduction == other.mIsProduction) \
|
||||||
|
&& (mIsUnqualifiedApproval == other.mIsUnqualifiedApproval) \
|
||||||
&& (mAcidSize == other.mAcidSize) \
|
&& (mAcidSize == other.mAcidSize) \
|
||||||
|
&& (mProgramIdMin == other.mProgramIdMin) \
|
||||||
|
&& (mProgramIdMax == other.mProgramIdMax) \
|
||||||
&& (mProgramId == other.mProgramId) \
|
&& (mProgramId == other.mProgramId) \
|
||||||
&& (mFac == other.mFac) \
|
&& (mFac == other.mFac) \
|
||||||
&& (mSac == other.mSac) \
|
&& (mSac == other.mSac) \
|
||||||
|
@ -30,7 +34,11 @@ void AciHeader::copyFrom(const AciHeader & other)
|
||||||
{
|
{
|
||||||
mHeaderOffset = other.mHeaderOffset;
|
mHeaderOffset = other.mHeaderOffset;
|
||||||
mType = other.mType;
|
mType = other.mType;
|
||||||
|
mIsProduction = other.mIsProduction;
|
||||||
|
mIsUnqualifiedApproval = other.mIsUnqualifiedApproval;
|
||||||
mAcidSize = other.mAcidSize;
|
mAcidSize = other.mAcidSize;
|
||||||
|
mProgramIdMin = other.mProgramIdMin;
|
||||||
|
mProgramIdMax = other.mProgramIdMax;
|
||||||
mProgramId = other.mProgramId;
|
mProgramId = other.mProgramId;
|
||||||
mFac = other.mFac;
|
mFac = other.mFac;
|
||||||
mSac = other.mSac;
|
mSac = other.mSac;
|
||||||
|
@ -87,10 +95,10 @@ void AciHeader::exportBinary()
|
||||||
switch (mType)
|
switch (mType)
|
||||||
{
|
{
|
||||||
case (TYPE_ACI0):
|
case (TYPE_ACI0):
|
||||||
hdr->set_signature(aci::kAciStructSig.c_str());
|
memcpy(hdr->signature, aci::kAciStructSig.c_str(), 4);
|
||||||
break;
|
break;
|
||||||
case (TYPE_ACID):
|
case (TYPE_ACID):
|
||||||
hdr->set_signature(aci::kAciDescStructSig.c_str());
|
memcpy(hdr->signature, aci::kAciDescStructSig.c_str(), 4);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw fnd::Exception(kModuleName, "Unexpected ACI type");
|
throw fnd::Exception(kModuleName, "Unexpected ACI type");
|
||||||
|
@ -98,30 +106,32 @@ void AciHeader::exportBinary()
|
||||||
|
|
||||||
// set offset/size
|
// set offset/size
|
||||||
calculateSectionOffsets();
|
calculateSectionOffsets();
|
||||||
hdr->fac().set_offset(mFac.offset);
|
hdr->fac.offset = mFac.offset;
|
||||||
hdr->fac().set_size(mFac.size);
|
hdr->fac.size = mFac.size;
|
||||||
hdr->sac().set_offset(mSac.offset);
|
hdr->sac.offset = mSac.offset;
|
||||||
hdr->sac().set_size(mSac.size);
|
hdr->sac.size = mSac.size;
|
||||||
hdr->kc().set_offset(mKc.offset);
|
hdr->kc.offset = mKc.offset;
|
||||||
hdr->kc().set_size(mKc.size);
|
hdr->kc.size = mKc.size;
|
||||||
|
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
if (mIsProduction)
|
if (mIsProduction)
|
||||||
flags |= BIT(0);
|
flags |= _BIT(aci::FLAG_PRODUCTION);
|
||||||
|
if (mIsProduction)
|
||||||
|
flags |= _BIT(aci::FLAG_UNQUALIFIED_APPROVAL);
|
||||||
|
|
||||||
hdr->set_flags(flags);
|
hdr->flags = flags;
|
||||||
|
|
||||||
if (mType == TYPE_ACI0)
|
if (mType == TYPE_ACI0)
|
||||||
{
|
{
|
||||||
// set program
|
// set program
|
||||||
hdr->set_program_id(mProgramId);
|
hdr->program_id_info.program_id = mProgramId;
|
||||||
}
|
}
|
||||||
else if (mType == TYPE_ACID)
|
else if (mType == TYPE_ACID)
|
||||||
{
|
{
|
||||||
mAcidSize = getAciSize();
|
mAcidSize = getAciSize();
|
||||||
hdr->set_size(mAcidSize);
|
hdr->size = mAcidSize;
|
||||||
hdr->set_program_id_min(mProgramIdMin);
|
hdr->program_id_info.program_id_restrict.min = mProgramIdMin;
|
||||||
hdr->set_program_id_max(mProgramIdMax);
|
hdr->program_id_info.program_id_restrict.max = mProgramIdMax;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,11 +149,11 @@ void AciHeader::importBinary(const byte_t * bytes, size_t len)
|
||||||
|
|
||||||
sAciHeader* hdr = (sAciHeader*)mBinaryBlob.getBytes();
|
sAciHeader* hdr = (sAciHeader*)mBinaryBlob.getBytes();
|
||||||
|
|
||||||
if (memcmp(hdr->signature(), aci::kAciStructSig.c_str(), 4) == 0)
|
if (std::string(hdr->signature, 4) == aci::kAciStructSig)
|
||||||
{
|
{
|
||||||
mType = TYPE_ACI0;
|
mType = TYPE_ACI0;
|
||||||
}
|
}
|
||||||
else if (memcmp(hdr->signature(), aci::kAciDescStructSig.c_str(), 4) == 0)
|
else if (std::string(hdr->signature, 4) == aci::kAciDescStructSig)
|
||||||
{
|
{
|
||||||
mType = TYPE_ACID;
|
mType = TYPE_ACID;
|
||||||
}
|
}
|
||||||
|
@ -155,8 +165,9 @@ void AciHeader::importBinary(const byte_t * bytes, size_t len)
|
||||||
|
|
||||||
if (mType == TYPE_ACI0)
|
if (mType == TYPE_ACI0)
|
||||||
{
|
{
|
||||||
mProgramId = hdr->program_id();
|
mProgramId = hdr->program_id_info.program_id.get();
|
||||||
mIsProduction = false;
|
mIsProduction = false;
|
||||||
|
mIsUnqualifiedApproval = false;
|
||||||
mAcidSize = 0;
|
mAcidSize = 0;
|
||||||
mProgramIdMin = 0;
|
mProgramIdMin = 0;
|
||||||
mProgramIdMax = 0;
|
mProgramIdMax = 0;
|
||||||
|
@ -164,21 +175,22 @@ void AciHeader::importBinary(const byte_t * bytes, size_t len)
|
||||||
else if (mType == TYPE_ACID)
|
else if (mType == TYPE_ACID)
|
||||||
{
|
{
|
||||||
mProgramId = 0;
|
mProgramId = 0;
|
||||||
mIsProduction = (hdr->flags() & BIT(0)) == BIT(0);
|
mIsProduction = _HAS_BIT(hdr->flags.get(), aci::FLAG_PRODUCTION);
|
||||||
mAcidSize = hdr->size();
|
mIsUnqualifiedApproval = _HAS_BIT(hdr->flags.get(), aci::FLAG_UNQUALIFIED_APPROVAL);
|
||||||
mProgramIdMin = hdr->program_id_min();
|
mAcidSize = hdr->size.get();
|
||||||
mProgramIdMax = hdr->program_id_max();
|
mProgramIdMin = hdr->program_id_info.program_id_restrict.min.get();
|
||||||
|
mProgramIdMax = hdr->program_id_info.program_id_restrict.max.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// the header offset is the MIN(sac.offset, fac.offset, kc.offset) - sizeof(sHeader)
|
// 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), aci::kAciAlignSize)) - align(sizeof(sAciHeader), aci::kAciAlignSize);
|
mHeaderOffset = MAX(MIN(hdr->sac.offset.get(), MIN(hdr->fac.offset.get(), hdr->kc.offset.get())), align(sizeof(sAciHeader), aci::kAciAlignSize)) - align(sizeof(sAciHeader), aci::kAciAlignSize);
|
||||||
|
|
||||||
mFac.offset = hdr->fac().offset() - mHeaderOffset;
|
mFac.offset = hdr->fac.offset.get() - mHeaderOffset;
|
||||||
mFac.size = hdr->fac().size();
|
mFac.size = hdr->fac.size.get();
|
||||||
mSac.offset = hdr->sac().offset() - mHeaderOffset;
|
mSac.offset = hdr->sac.offset.get() - mHeaderOffset;
|
||||||
mSac.size = hdr->sac().size();
|
mSac.size = hdr->sac.size.get();
|
||||||
mKc.offset = hdr->kc().offset() - mHeaderOffset;
|
mKc.offset = hdr->kc.offset.get() - mHeaderOffset;
|
||||||
mKc.size = hdr->kc().size();
|
mKc.size = hdr->kc.size.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx::AciHeader::clear()
|
void nx::AciHeader::clear()
|
||||||
|
@ -191,6 +203,7 @@ void nx::AciHeader::clear()
|
||||||
mProgramIdMax = 0;
|
mProgramIdMax = 0;
|
||||||
mAcidSize = 0;
|
mAcidSize = 0;
|
||||||
mIsProduction = false;
|
mIsProduction = false;
|
||||||
|
mIsUnqualifiedApproval = false;
|
||||||
mFac.offset = 0;
|
mFac.offset = 0;
|
||||||
mFac.size = 0;
|
mFac.size = 0;
|
||||||
mSac.offset = 0;
|
mSac.offset = 0;
|
||||||
|
@ -261,6 +274,16 @@ void nx::AciHeader::setIsProduction(bool isProduction)
|
||||||
mIsProduction = isProduction;
|
mIsProduction = isProduction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool nx::AciHeader::isUnqualifiedApproval() const
|
||||||
|
{
|
||||||
|
return mIsUnqualifiedApproval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::AciHeader::setIsUnqualifiedApproval(bool isUnqualifiedApproval)
|
||||||
|
{
|
||||||
|
mIsUnqualifiedApproval = isUnqualifiedApproval;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t AciHeader::getProgramId() const
|
uint64_t AciHeader::getProgramId() const
|
||||||
{
|
{
|
||||||
return mProgramId;
|
return mProgramId;
|
||||||
|
|
|
@ -465,7 +465,9 @@ void NpdmProcess::displayAciHdr(const nx::AciHeader& aci)
|
||||||
{
|
{
|
||||||
|
|
||||||
printf(" ACID Size: %" PRIx64 "\n", aci.getAcidSize());
|
printf(" ACID Size: %" PRIx64 "\n", aci.getAcidSize());
|
||||||
printf(" Target: %s\n", kAcidTarget[aci.isProduction()].c_str());
|
printf(" Flags: \n");
|
||||||
|
printf(" Production: %s\n", aci.isProduction() ? "TRUE" : "FALSE");
|
||||||
|
printf(" UnqualifiedApproval: %s\n", aci.isUnqualifiedApproval() ? "TRUE" : "FALSE");
|
||||||
printf(" ProgramID Restriction\n");
|
printf(" ProgramID Restriction\n");
|
||||||
printf(" Min: %016" PRIx64 "\n", aci.getProgramIdMin());
|
printf(" Min: %016" PRIx64 "\n", aci.getProgramIdMin());
|
||||||
printf(" Max: %016" PRIx64 "\n", aci.getProgramIdMax());
|
printf(" Max: %016" PRIx64 "\n", aci.getProgramIdMax());
|
||||||
|
|
Loading…
Reference in a new issue