Merge pull request #8 from jakcron/npdm-development

[nx|nstool] Updated npdm->aci flag information. Also corrected some bugs
This commit is contained in:
Jack 2018-04-28 00:15:16 +08:00 committed by GitHub
commit 2b11b434b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 78 additions and 72 deletions

View file

@ -78,6 +78,8 @@ namespace nx
void setAciType(AciType type);
bool isProduction() const;
void setIsProduction(bool isProduction);
bool isUnqualifiedApproval() const;
void setIsUnqualifiedApproval(bool isUnqualifiedApproval);
const sSection& getFacPos() const;
void setFacSize(size_t size);
const sSection& getSacPos() const;
@ -103,6 +105,7 @@ namespace nx
size_t mHeaderOffset;
AciType mType;
bool mIsProduction;
bool mIsUnqualifiedApproval;
sSection mFac, mSac, mKc;
void calculateSectionOffsets();

View file

@ -12,56 +12,34 @@ namespace nx
const std::string kAciStructSig = "ACI0";
const std::string kAciDescStructSig = "ACID";
static const size_t kAciAlignSize = 0x10;
enum Flags
{
FLAG_PRODUCTION,
FLAG_UNQUALIFIED_APPROVAL
};
}
#pragma pack(push,1)
struct sAciHeader
{
private:
byte_t signature_[4];
uint32_t size_; // includes prefacing signature, set only in ACID made by SDK (it enables easy resigning)
char signature[4];
le_uint32_t size; // includes prefacing signature, set only in ACID made by SDK (it enables easy resigning)
byte_t reserved_0[4];
uint32_t flags_; // set in ACID only
uint64_t program_id_; // set only in ACI0 (since ACID is generic)
uint64_t program_id_max_;
le_uint32_t flags; // set in ACID only
union uProgramIdInfo
{
struct sRestrictProgramId
{
le_uint64_t min;
le_uint64_t max;
} program_id_restrict;
le_uint64_t program_id;
} program_id_info;
struct sAciSection
{
private:
uint32_t offset_; // aligned by 0x10 from the last one
uint32_t size_;
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_; }
le_uint32_t offset; // aligned by 0x10 from the last one
le_uint32_t size;
} fac, sac, kc;
};
#pragma pack(pop)
}

View file

@ -13,7 +13,11 @@ bool AciHeader::isEqual(const AciHeader & other) const
{
return (mHeaderOffset == other.mHeaderOffset) \
&& (mType == other.mType) \
&& (mIsProduction == other.mIsProduction) \
&& (mIsUnqualifiedApproval == other.mIsUnqualifiedApproval) \
&& (mAcidSize == other.mAcidSize) \
&& (mProgramIdMin == other.mProgramIdMin) \
&& (mProgramIdMax == other.mProgramIdMax) \
&& (mProgramId == other.mProgramId) \
&& (mFac == other.mFac) \
&& (mSac == other.mSac) \
@ -30,7 +34,11 @@ void AciHeader::copyFrom(const AciHeader & other)
{
mHeaderOffset = other.mHeaderOffset;
mType = other.mType;
mIsProduction = other.mIsProduction;
mIsUnqualifiedApproval = other.mIsUnqualifiedApproval;
mAcidSize = other.mAcidSize;
mProgramIdMin = other.mProgramIdMin;
mProgramIdMax = other.mProgramIdMax;
mProgramId = other.mProgramId;
mFac = other.mFac;
mSac = other.mSac;
@ -87,10 +95,10 @@ void AciHeader::exportBinary()
switch (mType)
{
case (TYPE_ACI0):
hdr->set_signature(aci::kAciStructSig.c_str());
memcpy(hdr->signature, aci::kAciStructSig.c_str(), 4);
break;
case (TYPE_ACID):
hdr->set_signature(aci::kAciDescStructSig.c_str());
memcpy(hdr->signature, aci::kAciDescStructSig.c_str(), 4);
break;
default:
throw fnd::Exception(kModuleName, "Unexpected ACI type");
@ -98,30 +106,32 @@ void AciHeader::exportBinary()
// 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->fac.offset = mFac.offset;
hdr->fac.size = mFac.size;
hdr->sac.offset = mSac.offset;
hdr->sac.size = mSac.size;
hdr->kc.offset = mKc.offset;
hdr->kc.size = mKc.size;
uint32_t flags = 0;
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)
{
// set program
hdr->set_program_id(mProgramId);
hdr->program_id_info.program_id = mProgramId;
}
else if (mType == TYPE_ACID)
{
mAcidSize = getAciSize();
hdr->set_size(mAcidSize);
hdr->set_program_id_min(mProgramIdMin);
hdr->set_program_id_max(mProgramIdMax);
hdr->size = mAcidSize;
hdr->program_id_info.program_id_restrict.min = mProgramIdMin;
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();
if (memcmp(hdr->signature(), aci::kAciStructSig.c_str(), 4) == 0)
if (std::string(hdr->signature, 4) == aci::kAciStructSig)
{
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;
}
@ -155,8 +165,9 @@ void AciHeader::importBinary(const byte_t * bytes, size_t len)
if (mType == TYPE_ACI0)
{
mProgramId = hdr->program_id();
mProgramId = hdr->program_id_info.program_id.get();
mIsProduction = false;
mIsUnqualifiedApproval = false;
mAcidSize = 0;
mProgramIdMin = 0;
mProgramIdMax = 0;
@ -164,21 +175,22 @@ void AciHeader::importBinary(const byte_t * bytes, size_t len)
else if (mType == TYPE_ACID)
{
mProgramId = 0;
mIsProduction = (hdr->flags() & BIT(0)) == BIT(0);
mAcidSize = hdr->size();
mProgramIdMin = hdr->program_id_min();
mProgramIdMax = hdr->program_id_max();
mIsProduction = _HAS_BIT(hdr->flags.get(), aci::FLAG_PRODUCTION);
mIsUnqualifiedApproval = _HAS_BIT(hdr->flags.get(), aci::FLAG_UNQUALIFIED_APPROVAL);
mAcidSize = hdr->size.get();
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)
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.size = hdr->fac().size();
mSac.offset = hdr->sac().offset() - mHeaderOffset;
mSac.size = hdr->sac().size();
mKc.offset = hdr->kc().offset() - mHeaderOffset;
mKc.size = hdr->kc().size();
mFac.offset = hdr->fac.offset.get() - mHeaderOffset;
mFac.size = hdr->fac.size.get();
mSac.offset = hdr->sac.offset.get() - mHeaderOffset;
mSac.size = hdr->sac.size.get();
mKc.offset = hdr->kc.offset.get() - mHeaderOffset;
mKc.size = hdr->kc.size.get();
}
void nx::AciHeader::clear()
@ -191,6 +203,7 @@ void nx::AciHeader::clear()
mProgramIdMax = 0;
mAcidSize = 0;
mIsProduction = false;
mIsUnqualifiedApproval = false;
mFac.offset = 0;
mFac.size = 0;
mSac.offset = 0;
@ -261,6 +274,16 @@ void nx::AciHeader::setIsProduction(bool isProduction)
mIsProduction = isProduction;
}
bool nx::AciHeader::isUnqualifiedApproval() const
{
return mIsUnqualifiedApproval;
}
void nx::AciHeader::setIsUnqualifiedApproval(bool isUnqualifiedApproval)
{
mIsUnqualifiedApproval = isUnqualifiedApproval;
}
uint64_t AciHeader::getProgramId() const
{
return mProgramId;

View file

@ -465,7 +465,9 @@ void NpdmProcess::displayAciHdr(const nx::AciHeader& aci)
{
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(" Min: %016" PRIx64 "\n", aci.getProgramIdMin());
printf(" Max: %016" PRIx64 "\n", aci.getProgramIdMax());