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); 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();

View file

@ -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)
} }

View file

@ -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;

View file

@ -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());