mirror of
https://github.com/jakcron/nstool
synced 2024-12-24 21:51:14 +00:00
[nx|nstool] Added support for reading ContentMeta (.cnmt).
This commit is contained in:
parent
b36875661e
commit
79c24153bb
21 changed files with 589 additions and 190 deletions
|
@ -2,7 +2,7 @@
|
|||
#include <string>
|
||||
#include <fnd/MemoryBlob.h>
|
||||
#include <fnd/List.h>
|
||||
#include <nx/cmnt.h>
|
||||
#include <nx/cnmt.h>
|
||||
|
||||
|
||||
namespace nx
|
||||
|
@ -14,14 +14,14 @@ namespace nx
|
|||
struct ContentInfo
|
||||
{
|
||||
crypto::sha::sSha256Hash hash;
|
||||
byte_t nca_id[cmnt::kContentIdLen];
|
||||
byte_t nca_id[cnmt::kContentIdLen];
|
||||
size_t size;
|
||||
cmnt::ContentType type;
|
||||
cnmt::ContentType type;
|
||||
|
||||
ContentInfo& operator=(const ContentInfo& other)
|
||||
{
|
||||
hash = other.hash;
|
||||
memcpy(nca_id, other.nca_id, cmnt::kContentIdLen);
|
||||
memcpy(nca_id, other.nca_id, cnmt::kContentIdLen);
|
||||
size = other.size;
|
||||
type = other.type;
|
||||
return *this;
|
||||
|
@ -30,7 +30,7 @@ namespace nx
|
|||
bool operator==(const ContentInfo& other) const
|
||||
{
|
||||
return (hash == other.hash) \
|
||||
&& (memcmp(nca_id, other.nca_id, cmnt::kContentIdLen) == 0) \
|
||||
&& (memcmp(nca_id, other.nca_id, cnmt::kContentIdLen) == 0) \
|
||||
&& (size == other.size) \
|
||||
&& (type == other.type);
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ namespace nx
|
|||
{
|
||||
uint64_t id;
|
||||
uint32_t version;
|
||||
cmnt::ContentMetaType type;
|
||||
cnmt::ContentMetaType type;
|
||||
byte_t attributes;
|
||||
|
||||
ContentMetaInfo& operator=(const ContentMetaInfo& other)
|
||||
|
@ -71,6 +71,99 @@ namespace nx
|
|||
}
|
||||
};
|
||||
|
||||
struct ApplicationMetaExtendedHeader
|
||||
{
|
||||
uint64_t patch_id;
|
||||
uint32_t required_system_version;
|
||||
|
||||
ApplicationMetaExtendedHeader& operator=(const ApplicationMetaExtendedHeader& other)
|
||||
{
|
||||
patch_id = other.patch_id;
|
||||
required_system_version = other.required_system_version;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const ApplicationMetaExtendedHeader& other) const
|
||||
{
|
||||
return (patch_id == other.patch_id) \
|
||||
&& (required_system_version == other.required_system_version);
|
||||
}
|
||||
|
||||
bool operator!=(const ApplicationMetaExtendedHeader& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
};
|
||||
|
||||
struct PatchMetaExtendedHeader
|
||||
{
|
||||
uint64_t application_id;
|
||||
uint32_t required_system_version;
|
||||
|
||||
PatchMetaExtendedHeader& operator=(const PatchMetaExtendedHeader& other)
|
||||
{
|
||||
application_id = other.application_id;
|
||||
required_system_version = other.required_system_version;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const PatchMetaExtendedHeader& other) const
|
||||
{
|
||||
return (application_id == other.application_id) \
|
||||
&& (required_system_version == other.required_system_version);
|
||||
}
|
||||
|
||||
bool operator!=(const PatchMetaExtendedHeader& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
};
|
||||
|
||||
struct AddOnContentMetaExtendedHeader
|
||||
{
|
||||
uint64_t application_id;
|
||||
uint32_t required_system_version;
|
||||
|
||||
AddOnContentMetaExtendedHeader& operator=(const AddOnContentMetaExtendedHeader& other)
|
||||
{
|
||||
application_id = other.application_id;
|
||||
required_system_version = other.required_system_version;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const AddOnContentMetaExtendedHeader& other) const
|
||||
{
|
||||
return (application_id == other.application_id) \
|
||||
&& (required_system_version == other.required_system_version);
|
||||
}
|
||||
|
||||
bool operator!=(const AddOnContentMetaExtendedHeader& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
};
|
||||
|
||||
struct DeltaMetaExtendedHeader
|
||||
{
|
||||
uint64_t application_id;
|
||||
|
||||
DeltaMetaExtendedHeader& operator=(const DeltaMetaExtendedHeader& other)
|
||||
{
|
||||
application_id = other.application_id;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const DeltaMetaExtendedHeader& other) const
|
||||
{
|
||||
return (application_id == other.application_id);
|
||||
}
|
||||
|
||||
bool operator!=(const DeltaMetaExtendedHeader& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
};
|
||||
|
||||
ContentMetaBinary();
|
||||
ContentMetaBinary(const ContentMetaBinary& other);
|
||||
ContentMetaBinary(const byte_t* bytes, size_t len);
|
||||
|
@ -92,14 +185,26 @@ namespace nx
|
|||
uint32_t getTitleVersion() const;
|
||||
void setTitleVersion(uint32_t version);
|
||||
|
||||
cmnt::ContentMetaType getType() const;
|
||||
void setType(cmnt::ContentMetaType type);
|
||||
cnmt::ContentMetaType getType() const;
|
||||
void setType(cnmt::ContentMetaType type);
|
||||
|
||||
byte_t getAttributes() const;
|
||||
void setAttributes(byte_t attributes);
|
||||
|
||||
uint32_t getRequiredSystemVersion() const;
|
||||
void setRequiredSystemVersion(uint32_t version);
|
||||
uint32_t getRequiredDownloadSystemVersion() const;
|
||||
void setRequiredDownloadSystemVersion(uint32_t version);
|
||||
|
||||
const ApplicationMetaExtendedHeader& getApplicationMetaExtendedHeader() const;
|
||||
void setApplicationMetaExtendedHeader(const ApplicationMetaExtendedHeader& exhdr);
|
||||
|
||||
const PatchMetaExtendedHeader& getPatchMetaExtendedHeader() const;
|
||||
void setPatchMetaExtendedHeader(const PatchMetaExtendedHeader& exhdr);
|
||||
|
||||
const AddOnContentMetaExtendedHeader& getAddOnContentMetaExtendedHeader() const;
|
||||
void setAddOnContentMetaExtendedHeader(const AddOnContentMetaExtendedHeader& exhdr);
|
||||
|
||||
const DeltaMetaExtendedHeader& getDeltaMetaExtendedHeader() const;
|
||||
void setDeltaMetaExtendedHeader(const DeltaMetaExtendedHeader& exhdr);
|
||||
|
||||
const fnd::List<nx::ContentMetaBinary::ContentInfo>& getContentInfo() const;
|
||||
void setContentInfo(const fnd::List<nx::ContentMetaBinary::ContentInfo>& info);
|
||||
|
@ -123,10 +228,16 @@ namespace nx
|
|||
// variables
|
||||
uint64_t mTitleId;
|
||||
uint32_t mTitleVersion;
|
||||
cmnt::ContentMetaType mType;
|
||||
cnmt::ContentMetaType mType;
|
||||
byte_t mAttributes;
|
||||
uint32_t mRequiredSystemVersion;
|
||||
uint32_t mRequiredDownloadSystemVersion;
|
||||
fnd::MemoryBlob mExtendedHeader;
|
||||
|
||||
ApplicationMetaExtendedHeader mApplicationMetaExtendedHeader;
|
||||
PatchMetaExtendedHeader mPatchMetaExtendedHeader;
|
||||
AddOnContentMetaExtendedHeader mAddOnContentMetaExtendedHeader;
|
||||
DeltaMetaExtendedHeader mDeltaMetaExtendedHeader;
|
||||
|
||||
fnd::List<nx::ContentMetaBinary::ContentInfo> mContentInfo;
|
||||
fnd::List<nx::ContentMetaBinary::ContentMetaInfo> mContentMetaInfo;
|
||||
fnd::MemoryBlob mExtendedData;
|
||||
|
@ -137,11 +248,11 @@ namespace nx
|
|||
inline size_t getContentMetaInfoOffset(size_t exhdrSize, size_t contentInfoNum) const { return getContentInfoOffset(exhdrSize) + contentInfoNum * sizeof(sContentInfo); }
|
||||
inline size_t getExtendedDataOffset(size_t exhdrSize, size_t contentInfoNum, size_t contentMetaNum) const { return getContentMetaInfoOffset(exhdrSize, contentInfoNum) + contentMetaNum * sizeof(sContentMetaInfo); }
|
||||
inline size_t getDigestOffset(size_t exhdrSize, size_t contentInfoNum, size_t contentMetaNum, size_t exdataSize) const { return getExtendedDataOffset(exhdrSize, contentInfoNum, contentMetaNum) + exdataSize; }
|
||||
inline size_t getTotalSize(size_t exhdrSize, size_t contentInfoNum, size_t contentMetaNum, size_t exdataSize) const { return getDigestOffset(exhdrSize, contentInfoNum, contentMetaNum, exdataSize) + cmnt::kDigestLen; }
|
||||
inline size_t getTotalSize(size_t exhdrSize, size_t contentInfoNum, size_t contentMetaNum, size_t exdataSize) const { return getDigestOffset(exhdrSize, contentInfoNum, contentMetaNum, exdataSize) + cnmt::kDigestLen; }
|
||||
|
||||
bool validateExtendedHeaderSize(cmnt::ContentMetaType type, size_t exhdrSize);
|
||||
size_t getExtendedDataSize(cmnt::ContentMetaType type, const byte_t* data);
|
||||
void validateBinary(const byte_t* bytes, size_t len);
|
||||
bool validateExtendedHeaderSize(cnmt::ContentMetaType type, size_t exhdrSize) const;
|
||||
size_t getExtendedDataSize(cnmt::ContentMetaType type, const byte_t* data) const;
|
||||
void validateBinary(const byte_t* bytes, size_t len) const;
|
||||
|
||||
bool isEqual(const ContentMetaBinary& other) const;
|
||||
void copyFrom(const ContentMetaBinary& other);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace nx
|
||||
{
|
||||
namespace cmnt
|
||||
namespace cnmt
|
||||
{
|
||||
enum ContentType
|
||||
{
|
||||
|
@ -43,7 +43,6 @@ namespace nx
|
|||
|
||||
enum ContentMetaAttribute
|
||||
{
|
||||
ATTRIBUTE_NONE,
|
||||
ATTRIBUTE_INCLUDES_EX_FAT_DRIVER,
|
||||
ATTRIBUTE_REBOOTLESS
|
||||
};
|
||||
|
@ -79,14 +78,14 @@ namespace nx
|
|||
le_uint16_t content_meta_count;
|
||||
byte_t attributes;
|
||||
byte_t reserved_1[3];
|
||||
le_uint32_t required_system_version;
|
||||
le_uint32_t required_download_system_version;
|
||||
byte_t reserved_2[4];
|
||||
};
|
||||
|
||||
struct sContentInfo
|
||||
{
|
||||
crypto::sha::sSha256Hash content_hash;
|
||||
byte_t content_id[cmnt::kContentIdLen];
|
||||
byte_t content_id[cnmt::kContentIdLen];
|
||||
le_uint32_t size_lower;
|
||||
le_uint16_t size_higher;
|
||||
byte_t content_type;
|
||||
|
@ -104,14 +103,14 @@ namespace nx
|
|||
|
||||
struct sApplicationMetaExtendedHeader
|
||||
{
|
||||
le_uint64_t id;
|
||||
le_uint64_t patch_id;
|
||||
le_uint32_t required_system_version;
|
||||
byte_t reserved[4];
|
||||
};
|
||||
|
||||
struct sPatchMetaExtendedHeader
|
||||
{
|
||||
le_uint64_t id;
|
||||
le_uint64_t application_id;
|
||||
le_uint32_t required_system_version;
|
||||
le_uint32_t extended_data_size;
|
||||
byte_t reserved[8];
|
||||
|
@ -119,21 +118,21 @@ namespace nx
|
|||
|
||||
struct sAddOnContentMetaExtendedHeader
|
||||
{
|
||||
le_uint64_t id;
|
||||
le_uint64_t application_id;
|
||||
le_uint32_t required_system_version;
|
||||
byte_t reserved[4];
|
||||
};
|
||||
|
||||
struct sDeltaMetaExtendedHeader
|
||||
{
|
||||
le_uint64_t id;
|
||||
le_uint64_t application_id;
|
||||
le_uint32_t extended_data_size;
|
||||
byte_t reserved[4];
|
||||
};
|
||||
|
||||
struct sDigest
|
||||
{
|
||||
byte_t data[cmnt::kDigestLen];
|
||||
byte_t data[cnmt::kDigestLen];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
}
|
|
@ -43,9 +43,9 @@ void nx::ContentMetaBinary::importBinary(const byte_t * bytes, size_t len)
|
|||
|
||||
mTitleId = hdr->id.get();
|
||||
mTitleVersion = hdr->version.get();
|
||||
mType = (cmnt::ContentMetaType)hdr->type;
|
||||
mType = (cnmt::ContentMetaType)hdr->type;
|
||||
mAttributes = hdr->attributes;
|
||||
mRequiredSystemVersion = hdr->required_system_version.get();
|
||||
mRequiredDownloadSystemVersion = hdr->required_download_system_version.get();
|
||||
size_t exdata_size = 0;
|
||||
|
||||
// save exheader
|
||||
|
@ -54,6 +54,27 @@ void nx::ContentMetaBinary::importBinary(const byte_t * bytes, size_t len)
|
|||
mExtendedHeader.alloc(hdr->exhdr_size.get());
|
||||
memcpy(mExtendedHeader.getBytes(), bytes + getExtendedHeaderOffset(), hdr->exhdr_size.get());
|
||||
|
||||
switch (mType)
|
||||
{
|
||||
case (cnmt::METATYPE_APPLICATION):
|
||||
mApplicationMetaExtendedHeader.patch_id = ((sApplicationMetaExtendedHeader*)mExtendedHeader.getBytes())->patch_id.get();
|
||||
mApplicationMetaExtendedHeader.required_system_version = ((sApplicationMetaExtendedHeader*)mExtendedHeader.getBytes())->required_system_version.get();
|
||||
break;
|
||||
case (cnmt::METATYPE_PATCH):
|
||||
mPatchMetaExtendedHeader.application_id = ((sPatchMetaExtendedHeader*)mExtendedHeader.getBytes())->application_id.get();
|
||||
mPatchMetaExtendedHeader.required_system_version = ((sPatchMetaExtendedHeader*)mExtendedHeader.getBytes())->required_system_version.get();
|
||||
break;
|
||||
case (cnmt::METATYPE_ADD_ON_CONTENT):
|
||||
mAddOnContentMetaExtendedHeader.application_id = ((sAddOnContentMetaExtendedHeader*)mExtendedHeader.getBytes())->application_id.get();
|
||||
mAddOnContentMetaExtendedHeader.required_system_version = ((sAddOnContentMetaExtendedHeader*)mExtendedHeader.getBytes())->required_system_version.get();
|
||||
break;
|
||||
case (cnmt::METATYPE_DELTA):
|
||||
mDeltaMetaExtendedHeader.application_id = ((sDeltaMetaExtendedHeader*)mExtendedHeader.getBytes())->application_id.get();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
exdata_size = getExtendedDataSize(mType, mExtendedHeader.getBytes());
|
||||
}
|
||||
|
||||
|
@ -64,9 +85,9 @@ void nx::ContentMetaBinary::importBinary(const byte_t * bytes, size_t len)
|
|||
for (size_t i = 0; i < hdr->content_count.get(); i++)
|
||||
{
|
||||
mContentInfo[i].hash = info[i].content_hash;
|
||||
memcpy(mContentInfo[i].nca_id, info[i].content_id, cmnt::kContentIdLen);
|
||||
memcpy(mContentInfo[i].nca_id, info[i].content_id, cnmt::kContentIdLen);
|
||||
mContentInfo[i].size = (uint64_t)(info[i].size_lower.get()) | (uint64_t)(info[i].size_higher.get()) << 32;
|
||||
mContentInfo[i].type = (cmnt::ContentType)info[i].content_type;
|
||||
mContentInfo[i].type = (cnmt::ContentType)info[i].content_type;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +99,7 @@ void nx::ContentMetaBinary::importBinary(const byte_t * bytes, size_t len)
|
|||
{
|
||||
mContentMetaInfo[i].id = info[i].id.get();
|
||||
mContentMetaInfo[i].version = info[i].version.get();
|
||||
mContentMetaInfo[i].type = (cmnt::ContentMetaType)info[i].type;
|
||||
mContentMetaInfo[i].type = (cnmt::ContentMetaType)info[i].type;
|
||||
mContentMetaInfo[i].attributes = info[i].attributes;
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +112,7 @@ void nx::ContentMetaBinary::importBinary(const byte_t * bytes, size_t len)
|
|||
}
|
||||
|
||||
// save digest
|
||||
memcpy(mDigest.data, bytes + getDigestOffset(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get(), exdata_size), cmnt::kDigestLen);
|
||||
memcpy(mDigest.data, bytes + getDigestOffset(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get(), exdata_size), cnmt::kDigestLen);
|
||||
|
||||
}
|
||||
|
||||
|
@ -100,14 +121,18 @@ void nx::ContentMetaBinary::clear()
|
|||
mBinaryBlob.clear();
|
||||
mTitleId = 0;
|
||||
mTitleVersion = 0;
|
||||
mType = cmnt::METATYPE_SYSTEM_PROGRAM;
|
||||
mAttributes = cmnt::ATTRIBUTE_NONE;
|
||||
mRequiredSystemVersion = 0;
|
||||
mType = cnmt::METATYPE_SYSTEM_PROGRAM;
|
||||
mAttributes = 0;
|
||||
mRequiredDownloadSystemVersion = 0;
|
||||
mExtendedHeader.clear();
|
||||
memset(&mApplicationMetaExtendedHeader, 0, sizeof(mApplicationMetaExtendedHeader));
|
||||
memset(&mPatchMetaExtendedHeader, 0, sizeof(mPatchMetaExtendedHeader));
|
||||
memset(&mAddOnContentMetaExtendedHeader, 0, sizeof(mAddOnContentMetaExtendedHeader));
|
||||
memset(&mDeltaMetaExtendedHeader, 0, sizeof(mDeltaMetaExtendedHeader));
|
||||
mContentInfo.clear();
|
||||
mContentMetaInfo.clear();
|
||||
mExtendedData.clear();
|
||||
memset(mDigest.data, 0, cmnt::kDigestLen);
|
||||
memset(mDigest.data, 0, cnmt::kDigestLen);
|
||||
}
|
||||
|
||||
uint64_t nx::ContentMetaBinary::getTitleId() const
|
||||
|
@ -130,12 +155,12 @@ void nx::ContentMetaBinary::setTitleVersion(uint32_t version)
|
|||
mTitleVersion = version;
|
||||
}
|
||||
|
||||
nx::cmnt::ContentMetaType nx::ContentMetaBinary::getType() const
|
||||
nx::cnmt::ContentMetaType nx::ContentMetaBinary::getType() const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
void nx::ContentMetaBinary::setType(cmnt::ContentMetaType type)
|
||||
void nx::ContentMetaBinary::setType(cnmt::ContentMetaType type)
|
||||
{
|
||||
mType = type;
|
||||
}
|
||||
|
@ -150,14 +175,54 @@ void nx::ContentMetaBinary::setAttributes(byte_t attributes)
|
|||
mAttributes = attributes;
|
||||
}
|
||||
|
||||
uint32_t nx::ContentMetaBinary::getRequiredSystemVersion() const
|
||||
uint32_t nx::ContentMetaBinary::getRequiredDownloadSystemVersion() const
|
||||
{
|
||||
return mRequiredSystemVersion;
|
||||
return mRequiredDownloadSystemVersion;
|
||||
}
|
||||
|
||||
void nx::ContentMetaBinary::setRequiredSystemVersion(uint32_t version)
|
||||
void nx::ContentMetaBinary::setRequiredDownloadSystemVersion(uint32_t version)
|
||||
{
|
||||
mRequiredSystemVersion = version;
|
||||
mRequiredDownloadSystemVersion = version;
|
||||
}
|
||||
|
||||
const nx::ContentMetaBinary::ApplicationMetaExtendedHeader& nx::ContentMetaBinary::getApplicationMetaExtendedHeader() const
|
||||
{
|
||||
return mApplicationMetaExtendedHeader;
|
||||
}
|
||||
|
||||
void nx::ContentMetaBinary::setApplicationMetaExtendedHeader(const ApplicationMetaExtendedHeader& exhdr)
|
||||
{
|
||||
mApplicationMetaExtendedHeader = exhdr;
|
||||
}
|
||||
|
||||
const nx::ContentMetaBinary::PatchMetaExtendedHeader& nx::ContentMetaBinary::getPatchMetaExtendedHeader() const
|
||||
{
|
||||
return mPatchMetaExtendedHeader;
|
||||
}
|
||||
|
||||
void nx::ContentMetaBinary::setPatchMetaExtendedHeader(const PatchMetaExtendedHeader& exhdr)
|
||||
{
|
||||
mPatchMetaExtendedHeader = exhdr;
|
||||
}
|
||||
|
||||
const nx::ContentMetaBinary::AddOnContentMetaExtendedHeader& nx::ContentMetaBinary::getAddOnContentMetaExtendedHeader() const
|
||||
{
|
||||
return mAddOnContentMetaExtendedHeader;
|
||||
}
|
||||
|
||||
void nx::ContentMetaBinary::setAddOnContentMetaExtendedHeader(const AddOnContentMetaExtendedHeader& exhdr)
|
||||
{
|
||||
mAddOnContentMetaExtendedHeader = exhdr;
|
||||
}
|
||||
|
||||
const nx::ContentMetaBinary::DeltaMetaExtendedHeader& nx::ContentMetaBinary::getDeltaMetaExtendedHeader() const
|
||||
{
|
||||
return mDeltaMetaExtendedHeader;
|
||||
}
|
||||
|
||||
void nx::ContentMetaBinary::setDeltaMetaExtendedHeader(const DeltaMetaExtendedHeader& exhdr)
|
||||
{
|
||||
mDeltaMetaExtendedHeader = exhdr;
|
||||
}
|
||||
|
||||
const fnd::List<nx::ContentMetaBinary::ContentInfo>& nx::ContentMetaBinary::getContentInfo() const
|
||||
|
@ -198,34 +263,43 @@ const nx::sDigest & nx::ContentMetaBinary::getDigest() const
|
|||
void nx::ContentMetaBinary::setDigest(const nx::sDigest & digest)
|
||||
{
|
||||
|
||||
memcpy(mDigest.data, digest.data, cmnt::kDigestLen);
|
||||
memcpy(mDigest.data, digest.data, cnmt::kDigestLen);
|
||||
}
|
||||
|
||||
bool nx::ContentMetaBinary::validateExtendedHeaderSize(cmnt::ContentMetaType type, size_t exhdrSize)
|
||||
bool nx::ContentMetaBinary::validateExtendedHeaderSize(cnmt::ContentMetaType type, size_t exhdrSize) const
|
||||
{
|
||||
bool validSize = false;
|
||||
|
||||
if (type == cmnt::METATYPE_APPLICATION && exhdrSize == sizeof(sApplicationMetaExtendedHeader))
|
||||
validSize = true;
|
||||
else if (type == cmnt::METATYPE_PATCH && exhdrSize == sizeof(sPatchMetaExtendedHeader))
|
||||
validSize = true;
|
||||
else if (type == cmnt::METATYPE_ADD_ON_CONTENT && exhdrSize == sizeof(sAddOnContentMetaExtendedHeader))
|
||||
validSize = true;
|
||||
else if (type == cmnt::METATYPE_DELTA && exhdrSize == sizeof(sDeltaMetaExtendedHeader))
|
||||
validSize = true;
|
||||
switch (type)
|
||||
{
|
||||
case (cnmt::METATYPE_APPLICATION):
|
||||
validSize = (exhdrSize == sizeof(sApplicationMetaExtendedHeader));
|
||||
break;
|
||||
case (cnmt::METATYPE_PATCH):
|
||||
validSize = (exhdrSize == sizeof(sPatchMetaExtendedHeader));
|
||||
break;
|
||||
case (cnmt::METATYPE_ADD_ON_CONTENT):
|
||||
validSize = (exhdrSize == sizeof(sAddOnContentMetaExtendedHeader));
|
||||
break;
|
||||
case (cnmt::METATYPE_DELTA):
|
||||
validSize = (exhdrSize == sizeof(sDeltaMetaExtendedHeader));
|
||||
break;
|
||||
default:
|
||||
validSize = (exhdrSize == 0);
|
||||
}
|
||||
|
||||
return validSize;
|
||||
}
|
||||
|
||||
size_t nx::ContentMetaBinary::getExtendedDataSize(cmnt::ContentMetaType type, const byte_t * data)
|
||||
size_t nx::ContentMetaBinary::getExtendedDataSize(cnmt::ContentMetaType type, const byte_t * data) const
|
||||
{
|
||||
size_t exdata_len = 0;
|
||||
if (type == cmnt::METATYPE_PATCH)
|
||||
if (type == cnmt::METATYPE_PATCH)
|
||||
{
|
||||
const sPatchMetaExtendedHeader* exhdr = (const sPatchMetaExtendedHeader*)(data);
|
||||
exdata_len = exhdr->extended_data_size.get();
|
||||
}
|
||||
else if (type == cmnt::METATYPE_DELTA)
|
||||
else if (type == cnmt::METATYPE_DELTA)
|
||||
{
|
||||
const sDeltaMetaExtendedHeader* exhdr = (const sDeltaMetaExtendedHeader*)(data);
|
||||
exdata_len = exhdr->extended_data_size.get();
|
||||
|
@ -233,7 +307,7 @@ size_t nx::ContentMetaBinary::getExtendedDataSize(cmnt::ContentMetaType type, co
|
|||
return exdata_len;
|
||||
}
|
||||
|
||||
void nx::ContentMetaBinary::validateBinary(const byte_t * bytes, size_t len)
|
||||
void nx::ContentMetaBinary::validateBinary(const byte_t * bytes, size_t len) const
|
||||
{
|
||||
// check if it is large enough to read the header
|
||||
if (len < sizeof(sContentMetaHeader))
|
||||
|
@ -245,7 +319,7 @@ void nx::ContentMetaBinary::validateBinary(const byte_t * bytes, size_t len)
|
|||
const sContentMetaHeader* hdr = (const sContentMetaHeader*)bytes;
|
||||
|
||||
// validate extended header size
|
||||
if (validateExtendedHeaderSize((cmnt::ContentMetaType)hdr->type, hdr->exhdr_size.get()) == false)
|
||||
if (validateExtendedHeaderSize((cnmt::ContentMetaType)hdr->type, hdr->exhdr_size.get()) == false)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "Invalid extended header size");
|
||||
}
|
||||
|
@ -257,7 +331,7 @@ void nx::ContentMetaBinary::validateBinary(const byte_t * bytes, size_t len)
|
|||
}
|
||||
|
||||
// check binary size again with extended data size
|
||||
if (len < getTotalSize(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get(), getExtendedDataSize((cmnt::ContentMetaType)hdr->type, bytes + getExtendedHeaderOffset())))
|
||||
if (len < getTotalSize(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get(), getExtendedDataSize((cnmt::ContentMetaType)hdr->type, bytes + getExtendedHeaderOffset())))
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "Binary too small");
|
||||
}
|
||||
|
@ -269,12 +343,16 @@ bool nx::ContentMetaBinary::isEqual(const ContentMetaBinary & other) const
|
|||
&& (mTitleVersion == other.mTitleVersion) \
|
||||
&& (mType == other.mType) \
|
||||
&& (mAttributes == other.mAttributes) \
|
||||
&& (mRequiredSystemVersion == other.mRequiredSystemVersion) \
|
||||
&& (mRequiredDownloadSystemVersion == other.mRequiredDownloadSystemVersion) \
|
||||
&& (mExtendedHeader == other.mExtendedHeader) \
|
||||
&& (mApplicationMetaExtendedHeader == other.mApplicationMetaExtendedHeader) \
|
||||
&& (mPatchMetaExtendedHeader == other.mPatchMetaExtendedHeader) \
|
||||
&& (mAddOnContentMetaExtendedHeader == other.mAddOnContentMetaExtendedHeader) \
|
||||
&& (mDeltaMetaExtendedHeader == other.mDeltaMetaExtendedHeader) \
|
||||
&& (mContentInfo == other.mContentInfo) \
|
||||
&& (mContentMetaInfo == other.mContentMetaInfo) \
|
||||
&& (mExtendedData == other.mExtendedData) \
|
||||
&& (memcmp(mDigest.data, other.mDigest.data, cmnt::kDigestLen) == 0);
|
||||
&& (memcmp(mDigest.data, other.mDigest.data, cnmt::kDigestLen) == 0);
|
||||
}
|
||||
|
||||
void nx::ContentMetaBinary::copyFrom(const ContentMetaBinary & other)
|
||||
|
@ -290,11 +368,15 @@ void nx::ContentMetaBinary::copyFrom(const ContentMetaBinary & other)
|
|||
mTitleVersion = other.mTitleVersion;
|
||||
mType = other.mType;
|
||||
mAttributes = other.mAttributes;
|
||||
mRequiredSystemVersion = other.mRequiredSystemVersion;
|
||||
mRequiredDownloadSystemVersion = other.mRequiredDownloadSystemVersion;
|
||||
mExtendedHeader = other.mExtendedHeader;
|
||||
mApplicationMetaExtendedHeader = other.mApplicationMetaExtendedHeader;
|
||||
mPatchMetaExtendedHeader = other.mPatchMetaExtendedHeader;
|
||||
mAddOnContentMetaExtendedHeader = other.mAddOnContentMetaExtendedHeader;
|
||||
mDeltaMetaExtendedHeader = other.mDeltaMetaExtendedHeader;
|
||||
mContentInfo = other.mContentInfo;
|
||||
mContentMetaInfo = other.mContentMetaInfo;
|
||||
mExtendedData = other.mExtendedData;
|
||||
memcpy(mDigest.data, other.mDigest.data, cmnt::kDigestLen);
|
||||
memcpy(mDigest.data, other.mDigest.data, cnmt::kDigestLen);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
#include "CmntProcess.h"
|
|
@ -1 +0,0 @@
|
|||
#pragma once
|
185
programs/nstool/source/CnmtProcess.cpp
Normal file
185
programs/nstool/source/CnmtProcess.cpp
Normal file
|
@ -0,0 +1,185 @@
|
|||
#include <fnd/SimpleTextOutput.h>
|
||||
#include "OffsetAdjustedIFile.h"
|
||||
#include "CnmtProcess.h"
|
||||
|
||||
const std::string kContentTypeStr[7] =
|
||||
{
|
||||
"Meta",
|
||||
"Program",
|
||||
"Data",
|
||||
"Control",
|
||||
"HtmlDocument",
|
||||
"LegalInformation",
|
||||
"DeltaFragment"
|
||||
};
|
||||
|
||||
const std::string kContentMetaTypeStr[2][0x80] =
|
||||
{
|
||||
{
|
||||
""
|
||||
"SystemProgram",
|
||||
"SystemData",
|
||||
"SystemUpdate",
|
||||
"BootImagePackage",
|
||||
"BootImagePackageSafe"
|
||||
},
|
||||
{
|
||||
"Application",
|
||||
"Patch",
|
||||
"AddOnContent",
|
||||
"Delta"
|
||||
}
|
||||
};
|
||||
|
||||
inline const std::string& getContentMetaTypeStr(byte_t index)
|
||||
{
|
||||
return (index < 0x80) ? kContentMetaTypeStr[0][index] : kContentMetaTypeStr[1][index-0x80];
|
||||
}
|
||||
|
||||
const std::string kUpdateTypeStr[3] =
|
||||
{
|
||||
"ApplyAsDelta",
|
||||
"Overwrite",
|
||||
"Create"
|
||||
};
|
||||
|
||||
const std::string kContentMetaAttrStr[3] =
|
||||
{
|
||||
"IncludesExFatDriver",
|
||||
"Rebootless"
|
||||
};
|
||||
|
||||
inline const char* getBoolStr(bool isTrue)
|
||||
{
|
||||
return isTrue? "TRUE" : "FALSE";
|
||||
}
|
||||
|
||||
void CnmtProcess::displayCmnt()
|
||||
{
|
||||
#define _SPLIT_VER(ver) ( (ver>>24) & 0xff), ( (ver>>16) & 0xff), ( (ver>>8) & 0xff), (ver & 0xff)
|
||||
|
||||
printf("[ContentMeta]\n");
|
||||
printf(" TitleId: 0x%" PRIx64 "\n", mCnmt.getTitleId());
|
||||
uint32_t ver = mCnmt.getTitleVersion();
|
||||
printf(" Version: v%d.%d.%d-%d (v%" PRId32 ")\n", _SPLIT_VER(ver), ver);
|
||||
printf(" Type: %s\n", getContentMetaTypeStr(mCnmt.getType()).c_str());
|
||||
printf(" Attributes: %x\n", mCnmt.getAttributes());
|
||||
printf(" IncludesExFatDriver: %s\n", getBoolStr(_HAS_BIT(mCnmt.getAttributes(), nx::cnmt::ATTRIBUTE_INCLUDES_EX_FAT_DRIVER)));
|
||||
printf(" Rebootless: %s\n", getBoolStr(_HAS_BIT(mCnmt.getAttributes(), nx::cnmt::ATTRIBUTE_REBOOTLESS)));
|
||||
ver = mCnmt.getRequiredDownloadSystemVersion();
|
||||
printf(" RequiredDownloadSystemVersion: v%d.%d.%d-%d (v%" PRId32 ")\n", _SPLIT_VER(ver), ver);
|
||||
switch(mCnmt.getType())
|
||||
{
|
||||
case (nx::cnmt::METATYPE_APPLICATION):
|
||||
printf(" ApplicationExtendedHeader:\n");
|
||||
printf(" RequiredSystemVersion: %" PRId32 "\n", mCnmt.getApplicationMetaExtendedHeader().required_system_version);
|
||||
printf(" PatchId: 0x%016" PRIx64 "\n", mCnmt.getApplicationMetaExtendedHeader().patch_id);
|
||||
break;
|
||||
case (nx::cnmt::METATYPE_PATCH):
|
||||
printf(" PatchMetaExtendedHeader:\n");
|
||||
printf(" RequiredSystemVersion: %" PRId32 "\n", mCnmt.getPatchMetaExtendedHeader().required_system_version);
|
||||
printf(" ApplicationId: 0x%016" PRIx64 "\n", mCnmt.getPatchMetaExtendedHeader().application_id);
|
||||
break;
|
||||
case (nx::cnmt::METATYPE_ADD_ON_CONTENT):
|
||||
printf(" AddOnContentMetaExtendedHeader:\n");
|
||||
printf(" RequiredSystemVersion: %" PRId32 "\n", mCnmt.getAddOnContentMetaExtendedHeader().required_system_version);
|
||||
printf(" ApplicationId: 0x%016" PRIx64 "\n", mCnmt.getAddOnContentMetaExtendedHeader().application_id);
|
||||
break;
|
||||
case (nx::cnmt::METATYPE_DELTA):
|
||||
printf(" DeltaMetaExtendedHeader:\n");
|
||||
printf(" ApplicationId: 0x%016" PRIx64 "\n", mCnmt.getDeltaMetaExtendedHeader().application_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (mCnmt.getContentInfo().getSize() > 0)
|
||||
{
|
||||
printf(" ContentInfo:\n");
|
||||
for (size_t i = 0; i < mCnmt.getContentInfo().getSize(); i++)
|
||||
{
|
||||
const nx::ContentMetaBinary::ContentInfo& info = mCnmt.getContentInfo()[i];
|
||||
printf(" %d\n", i);
|
||||
printf(" Type: %s\n", kContentTypeStr[info.type].c_str());
|
||||
printf(" Id: ");
|
||||
fnd::SimpleTextOutput::hexDump(info.nca_id, nx::cnmt::kContentIdLen);
|
||||
printf(" Size: 0x%" PRIx64 "\n", info.size);
|
||||
printf(" Hash: ");
|
||||
fnd::SimpleTextOutput::hexDump(info.hash.bytes, sizeof(info.hash));
|
||||
}
|
||||
}
|
||||
if (mCnmt.getContentMetaInfo().getSize() > 0)
|
||||
{
|
||||
printf(" ContentMetaInfo:\n");
|
||||
for (size_t i = 0; i < mCnmt.getContentMetaInfo().getSize(); i++)
|
||||
{
|
||||
const nx::ContentMetaBinary::ContentMetaInfo& info = mCnmt.getContentMetaInfo()[i];
|
||||
printf(" %d\n", i);
|
||||
printf(" Id: 0x%" PRIx64 "\n", info.id);
|
||||
ver = info.version;
|
||||
printf(" Version: v%d.%d.%d-%d (v%" PRId32 ")\n", _SPLIT_VER(ver), ver);
|
||||
printf(" Type: %s\n", getContentMetaTypeStr(info.type).c_str());
|
||||
printf(" Attributes: %x\n", mCnmt.getAttributes());
|
||||
printf(" IncludesExFatDriver: %s\n", getBoolStr(_HAS_BIT(mCnmt.getAttributes(), nx::cnmt::ATTRIBUTE_INCLUDES_EX_FAT_DRIVER)));
|
||||
printf(" Rebootless: %s\n", getBoolStr(_HAS_BIT(mCnmt.getAttributes(), nx::cnmt::ATTRIBUTE_REBOOTLESS)));
|
||||
}
|
||||
}
|
||||
printf(" Digest: ");
|
||||
fnd::SimpleTextOutput::hexDump(mCnmt.getDigest().data, nx::cnmt::kDigestLen);
|
||||
|
||||
#undef _SPLIT_VER
|
||||
}
|
||||
|
||||
CnmtProcess::CnmtProcess() :
|
||||
mReader(nullptr),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mVerify(false)
|
||||
{
|
||||
}
|
||||
|
||||
CnmtProcess::~CnmtProcess()
|
||||
{
|
||||
if (mReader != nullptr)
|
||||
{
|
||||
delete mReader;
|
||||
}
|
||||
}
|
||||
|
||||
void CnmtProcess::process()
|
||||
{
|
||||
fnd::MemoryBlob scratch;
|
||||
|
||||
if (mReader == nullptr)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "No file reader set.");
|
||||
}
|
||||
|
||||
scratch.alloc(mReader->size());
|
||||
mReader->read(scratch.getBytes(), 0, scratch.getSize());
|
||||
|
||||
mCnmt.importBinary(scratch.getBytes(), scratch.getSize());
|
||||
|
||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||
{
|
||||
displayCmnt();
|
||||
}
|
||||
}
|
||||
|
||||
void CnmtProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size)
|
||||
{
|
||||
mReader = new OffsetAdjustedIFile(file, offset, size);
|
||||
}
|
||||
|
||||
void CnmtProcess::setCliOutputMode(CliOutputType type)
|
||||
{
|
||||
mCliOutputType = type;
|
||||
}
|
||||
|
||||
void CnmtProcess::setVerifyMode(bool verify)
|
||||
{
|
||||
mVerify = verify;
|
||||
}
|
||||
|
||||
const nx::ContentMetaBinary& CnmtProcess::getContentMetaBinary() const
|
||||
{
|
||||
return mCnmt;
|
||||
}
|
33
programs/nstool/source/CnmtProcess.h
Normal file
33
programs/nstool/source/CnmtProcess.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <fnd/types.h>
|
||||
#include <fnd/IFile.h>
|
||||
#include <nx/ContentMetaBinary.h>
|
||||
|
||||
#include "nstool.h"
|
||||
|
||||
class CnmtProcess
|
||||
{
|
||||
public:
|
||||
CnmtProcess();
|
||||
~CnmtProcess();
|
||||
|
||||
void process();
|
||||
|
||||
void setInputFile(fnd::IFile* file, size_t offset, size_t size);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
const nx::ContentMetaBinary& getContentMetaBinary() const;
|
||||
|
||||
private:
|
||||
const std::string kModuleName = "CnmtProcess";
|
||||
|
||||
fnd::IFile* mReader;
|
||||
CliOutputType mCliOutputType;
|
||||
bool mVerify;
|
||||
|
||||
nx::ContentMetaBinary mCnmt;
|
||||
|
||||
void displayCmnt();
|
||||
};
|
|
@ -2,10 +2,10 @@
|
|||
#include <fnd/SimpleTextOutput.h>
|
||||
#include <nx/NcaUtils.h>
|
||||
#include <nx/AesKeygen.h>
|
||||
#include <nx/NpdmBinary.h>
|
||||
#include "NcaProcess.h"
|
||||
#include "PfsProcess.h"
|
||||
#include "RomfsProcess.h"
|
||||
#include "NpdmProcess.h"
|
||||
#include "OffsetAdjustedIFile.h"
|
||||
#include "AesCtrWrappedIFile.h"
|
||||
#include "CopiedIFile.h"
|
||||
|
@ -199,10 +199,11 @@ void NcaProcess::generatePartitionConfiguration()
|
|||
throw fnd::Exception(kModuleName, error.str());
|
||||
}
|
||||
|
||||
// determine the data offset
|
||||
// determine the data offset & size
|
||||
if (mPartitions[partition.index].hash_type == nx::nca::HASH_HIERARCHICAL_SHA256)
|
||||
{
|
||||
mPartitions[partition.index].data_offset = mPartitions[partition.index].hierarchicalsha256_header.hash_target.offset.get();
|
||||
mPartitions[partition.index].data_size = mPartitions[partition.index].hierarchicalsha256_header.hash_target.size.get();
|
||||
}
|
||||
else if (mPartitions[partition.index].hash_type == nx::nca::HASH_HIERARCHICAL_INTERGRITY)
|
||||
{
|
||||
|
@ -211,6 +212,7 @@ void NcaProcess::generatePartitionConfiguration()
|
|||
if (mPartitions[partition.index].ivfc_header.level_header[nx::ivfc::kMaxIvfcLevel-1-j].logical_offset.get() != 0)
|
||||
{
|
||||
mPartitions[partition.index].data_offset = mPartitions[partition.index].ivfc_header.level_header[nx::ivfc::kMaxIvfcLevel-1-j].logical_offset.get();
|
||||
mPartitions[partition.index].data_size = mPartitions[partition.index].ivfc_header.level_header[nx::ivfc::kMaxIvfcLevel-1-j].hash_data_size.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -245,25 +247,21 @@ void NcaProcess::validateNcaSignatures()
|
|||
if (mPartitions[0].reader != nullptr)
|
||||
{
|
||||
PfsProcess exefs;
|
||||
exefs.setInputFile(mPartitions[0].reader);
|
||||
exefs.setInputFileOffset(mPartitions[0].offset + mPartitions[0].data_offset);
|
||||
exefs.setInputFile(mPartitions[0].reader, mPartitions[0].offset + mPartitions[0].data_offset, mPartitions[0].data_size);
|
||||
exefs.setCliOutputMode(OUTPUT_MINIMAL);
|
||||
exefs.process();
|
||||
|
||||
// open main.npdm
|
||||
if (exefs.getPfsHeader().getFileList().hasElement(kNpdmExefsPath) == true)
|
||||
{
|
||||
const nx::PfsHeader::sFile& npdmFile = exefs.getPfsHeader().getFileList()[exefs.getPfsHeader().getFileList().getIndexOf(kNpdmExefsPath)];
|
||||
const nx::PfsHeader::sFile& file = exefs.getPfsHeader().getFileList()[exefs.getPfsHeader().getFileList().getIndexOf(kNpdmExefsPath)];
|
||||
|
||||
fnd::MemoryBlob scratch;
|
||||
scratch.alloc(npdmFile.size);
|
||||
mPartitions[0].reader->read(scratch.getBytes(), mPartitions[0].offset + mPartitions[0].data_offset + npdmFile.offset, npdmFile.size);
|
||||
NpdmProcess npdm;
|
||||
npdm.setInputFile(mPartitions[0].reader, mPartitions[0].offset + mPartitions[0].data_offset + file.offset, file.size);
|
||||
npdm.setCliOutputMode(OUTPUT_MINIMAL);
|
||||
npdm.process();
|
||||
|
||||
nx::NpdmBinary npdmBinary;
|
||||
|
||||
npdmBinary.importBinary(scratch.getBytes(), scratch.getSize());
|
||||
|
||||
if (crypto::rsa::pss::rsaVerify(npdmBinary.getAcid().getNcaHeader2RsaKey(), crypto::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_acid) != 0)
|
||||
if (crypto::rsa::pss::rsaVerify(npdm.getNpdmBinary().getAcid().getNcaHeader2RsaKey(), crypto::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_acid) != 0)
|
||||
{
|
||||
// this is minimal even though it's a warning because it's a validation method
|
||||
if (mCliOutputType >= OUTPUT_MINIMAL)
|
||||
|
@ -429,8 +427,7 @@ void NcaProcess::processPartitions()
|
|||
if (partition.format_type == nx::nca::FORMAT_PFS0)
|
||||
{
|
||||
PfsProcess pfs;
|
||||
pfs.setInputFile(partition.reader);
|
||||
pfs.setInputFileOffset(partition.offset + partition.data_offset);
|
||||
pfs.setInputFile(partition.reader, partition.offset + partition.data_offset, partition.data_size);
|
||||
pfs.setCliOutputMode(mCliOutputType);
|
||||
pfs.setListFs(mListFs);
|
||||
if (mPartitionPath[index].doExtract)
|
||||
|
@ -442,8 +439,7 @@ void NcaProcess::processPartitions()
|
|||
else if (partition.format_type == nx::nca::FORMAT_ROMFS)
|
||||
{
|
||||
RomfsProcess romfs;
|
||||
romfs.setInputFile(partition.reader);
|
||||
romfs.setInputFileOffset(partition.offset + partition.data_offset);
|
||||
romfs.setInputFile(partition.reader, partition.offset + partition.data_offset, partition.data_size);
|
||||
romfs.setCliOutputMode(mCliOutputType);
|
||||
romfs.setListFs(mListFs);
|
||||
if (mPartitionPath[index].doExtract)
|
||||
|
@ -457,7 +453,6 @@ void NcaProcess::processPartitions()
|
|||
|
||||
NcaProcess::NcaProcess() :
|
||||
mReader(nullptr),
|
||||
mOffset(0),
|
||||
mKeyset(nullptr),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mVerify(false),
|
||||
|
@ -472,6 +467,11 @@ NcaProcess::NcaProcess() :
|
|||
|
||||
NcaProcess::~NcaProcess()
|
||||
{
|
||||
if (mReader != nullptr)
|
||||
{
|
||||
delete mReader;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < nx::nca::kPartitionNum; i++)
|
||||
{
|
||||
if (mPartitions[i].reader != nullptr)
|
||||
|
@ -491,7 +491,7 @@ void NcaProcess::process()
|
|||
}
|
||||
|
||||
// read header block
|
||||
mReader->read((byte_t*)&mHdrBlock, mOffset, sizeof(nx::sNcaHeaderBlock));
|
||||
mReader->read((byte_t*)&mHdrBlock, 0, sizeof(nx::sNcaHeaderBlock));
|
||||
|
||||
// decrypt header block
|
||||
nx::NcaUtils::decryptNcaHeader((byte_t*)&mHdrBlock, (byte_t*)&mHdrBlock, mKeyset->nca.header_key);
|
||||
|
@ -539,22 +539,11 @@ void NcaProcess::process()
|
|||
so the verification text can be presented without interuption
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// decrypt key area
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void NcaProcess::setInputFile(fnd::IFile* reader)
|
||||
void NcaProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size)
|
||||
{
|
||||
mReader = reader;
|
||||
}
|
||||
|
||||
void NcaProcess::setInputFileOffset(size_t offset)
|
||||
{
|
||||
mOffset = offset;
|
||||
mReader = new OffsetAdjustedIFile(file, offset, size);
|
||||
}
|
||||
|
||||
void NcaProcess::setKeyset(const sKeyset* keyset)
|
||||
|
|
|
@ -15,8 +15,7 @@ public:
|
|||
void process();
|
||||
|
||||
// generic
|
||||
void setInputFile(fnd::IFile* reader);
|
||||
void setInputFileOffset(size_t offset);
|
||||
void setInputFile(fnd::IFile* file, size_t offset, size_t size);
|
||||
void setKeyset(const sKeyset* keyset);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
@ -34,7 +33,6 @@ private:
|
|||
|
||||
// user options
|
||||
fnd::IFile* mReader;
|
||||
size_t mOffset;
|
||||
const sKeyset* mKeyset;
|
||||
CliOutputType mCliOutputType;
|
||||
bool mVerify;
|
||||
|
@ -63,8 +61,9 @@ private:
|
|||
{
|
||||
fnd::IFile* reader;
|
||||
size_t offset;
|
||||
size_t data_offset;
|
||||
size_t size;
|
||||
size_t data_offset;
|
||||
size_t data_size;
|
||||
nx::nca::FormatType format_type;
|
||||
nx::nca::HashType hash_type;
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "OffsetAdjustedIFile.h"
|
||||
#include "NpdmProcess.h"
|
||||
#include <fnd/SimpleFile.h>
|
||||
#include <fnd/MemoryBlob.h>
|
||||
|
||||
const std::string kInstructionType[2] = { "32Bit", "64Bit" };
|
||||
const std::string kProcAddrSpace[4] = { "Unknown", "64Bit", "32Bit", "32Bit no reserved" };
|
||||
|
@ -619,13 +618,20 @@ void NpdmProcess::displayKernelCap(const nx::KcBinary& kern)
|
|||
|
||||
NpdmProcess::NpdmProcess() :
|
||||
mReader(nullptr),
|
||||
mOffset(0),
|
||||
mKeyset(nullptr),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mVerify(false)
|
||||
{
|
||||
}
|
||||
|
||||
NpdmProcess::~NpdmProcess()
|
||||
{
|
||||
if (mReader != nullptr)
|
||||
{
|
||||
delete mReader;
|
||||
}
|
||||
}
|
||||
|
||||
void NpdmProcess::process()
|
||||
{
|
||||
fnd::MemoryBlob scratch;
|
||||
|
@ -665,14 +671,9 @@ void NpdmProcess::process()
|
|||
}
|
||||
}
|
||||
|
||||
void NpdmProcess::setInputFile(fnd::IFile* reader)
|
||||
void NpdmProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size)
|
||||
{
|
||||
mReader = reader;
|
||||
}
|
||||
|
||||
void NpdmProcess::setInputFileOffset(size_t offset)
|
||||
{
|
||||
mOffset = offset;
|
||||
mReader = new OffsetAdjustedIFile(file, offset, size);
|
||||
}
|
||||
|
||||
void NpdmProcess::setKeyset(const sKeyset* keyset)
|
||||
|
@ -688,4 +689,9 @@ void NpdmProcess::setCliOutputMode(CliOutputType type)
|
|||
void NpdmProcess::setVerifyMode(bool verify)
|
||||
{
|
||||
mVerify = verify;
|
||||
}
|
||||
|
||||
const nx::NpdmBinary& NpdmProcess::getNpdmBinary() const
|
||||
{
|
||||
return mNpdm;
|
||||
}
|
|
@ -10,20 +10,21 @@ class NpdmProcess
|
|||
{
|
||||
public:
|
||||
NpdmProcess();
|
||||
~NpdmProcess();
|
||||
|
||||
void process();
|
||||
|
||||
void setInputFile(fnd::IFile* reader);
|
||||
void setInputFileOffset(size_t offset);
|
||||
void setInputFile(fnd::IFile* file, size_t offset, size_t size);
|
||||
void setKeyset(const sKeyset* keyset);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
const nx::NpdmBinary& getNpdmBinary() const;
|
||||
|
||||
private:
|
||||
const std::string kModuleName = "NpdmProcess";
|
||||
|
||||
fnd::IFile* mReader;
|
||||
size_t mOffset;
|
||||
const sKeyset* mKeyset;
|
||||
CliOutputType mCliOutputType;
|
||||
bool mVerify;
|
||||
|
|
|
@ -16,7 +16,7 @@ size_t OffsetAdjustedIFile::size()
|
|||
|
||||
void OffsetAdjustedIFile::seek(size_t offset)
|
||||
{
|
||||
mCurrentOffset = offset;
|
||||
mCurrentOffset = MIN(offset, mSize);
|
||||
mFile->seek(offset + mBaseOffset);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "PfsProcess.h"
|
||||
#include <fnd/SimpleFile.h>
|
||||
#include <fnd/io.h>
|
||||
#include "OffsetAdjustedIFile.h"
|
||||
#include "PfsProcess.h"
|
||||
|
||||
void PfsProcess::displayHeader()
|
||||
{
|
||||
|
@ -55,7 +56,7 @@ void PfsProcess::validateHfs()
|
|||
for (size_t i = 0; i < file.getSize(); i++)
|
||||
{
|
||||
scratch.alloc(file[i].hash_protected_size);
|
||||
mReader->read(scratch.getBytes(), mOffset + file[i].offset, file[i].hash_protected_size);
|
||||
mReader->read(scratch.getBytes(), file[i].offset, file[i].hash_protected_size);
|
||||
crypto::sha::Sha256(scratch.getBytes(), scratch.getSize(), hash.bytes);
|
||||
if (hash != file[i].hash)
|
||||
{
|
||||
|
@ -85,7 +86,7 @@ void PfsProcess::extractFs()
|
|||
fnd::io::appendToPath(file_path, mExtractPath);
|
||||
fnd::io::appendToPath(file_path, file[i].name);
|
||||
outFile.open(file_path, outFile.Create);
|
||||
mReader->seek(mOffset + file[i].offset);
|
||||
mReader->seek(file[i].offset);
|
||||
for (size_t j = 0; j < (file[i].size / kFileExportBlockSize); j++)
|
||||
{
|
||||
mReader->read(scratch.getBytes(), kFileExportBlockSize);
|
||||
|
@ -102,8 +103,6 @@ void PfsProcess::extractFs()
|
|||
|
||||
PfsProcess::PfsProcess() :
|
||||
mReader(nullptr),
|
||||
mOffset(0),
|
||||
mKeyset(nullptr),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mVerify(false),
|
||||
mExtractPath(),
|
||||
|
@ -112,7 +111,14 @@ PfsProcess::PfsProcess() :
|
|||
mListFs(false),
|
||||
mPfs()
|
||||
{
|
||||
}
|
||||
|
||||
PfsProcess::~PfsProcess()
|
||||
{
|
||||
if (mReader != nullptr)
|
||||
{
|
||||
delete mReader;
|
||||
}
|
||||
}
|
||||
|
||||
void PfsProcess::process()
|
||||
|
@ -126,7 +132,7 @@ void PfsProcess::process()
|
|||
|
||||
// open minimum header to get full header size
|
||||
scratch.alloc(sizeof(nx::sPfsHeader));
|
||||
mReader->read(scratch.getBytes(), mOffset, scratch.getSize());
|
||||
mReader->read(scratch.getBytes(), 0, scratch.getSize());
|
||||
if (validateHeaderMagic(((nx::sPfsHeader*)scratch.getBytes())) == false)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "Corrupt Header");
|
||||
|
@ -135,7 +141,7 @@ void PfsProcess::process()
|
|||
|
||||
// open minimum header to get full header size
|
||||
scratch.alloc(pfsHeaderSize);
|
||||
mReader->read(scratch.getBytes(), mOffset, scratch.getSize());
|
||||
mReader->read(scratch.getBytes(), 0, scratch.getSize());
|
||||
mPfs.importBinary(scratch.getBytes(), scratch.getSize());
|
||||
|
||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||
|
@ -148,19 +154,9 @@ void PfsProcess::process()
|
|||
extractFs();
|
||||
}
|
||||
|
||||
void PfsProcess::setInputFile(fnd::IFile* reader)
|
||||
void PfsProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size)
|
||||
{
|
||||
mReader = reader;
|
||||
}
|
||||
|
||||
void PfsProcess::setInputFileOffset(size_t offset)
|
||||
{
|
||||
mOffset = offset;
|
||||
}
|
||||
|
||||
void PfsProcess::setKeyset(const sKeyset* keyset)
|
||||
{
|
||||
mKeyset = keyset;
|
||||
mReader = new OffsetAdjustedIFile(file, offset, size);
|
||||
}
|
||||
|
||||
void PfsProcess::setCliOutputMode(CliOutputType type)
|
||||
|
|
|
@ -10,13 +10,12 @@ class PfsProcess
|
|||
{
|
||||
public:
|
||||
PfsProcess();
|
||||
~PfsProcess();
|
||||
|
||||
void process();
|
||||
|
||||
// generic
|
||||
void setInputFile(fnd::IFile* reader);
|
||||
void setInputFileOffset(size_t offset);
|
||||
void setKeyset(const sKeyset* keyset);
|
||||
void setInputFile(fnd::IFile* file, size_t offset, size_t size);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
|
@ -32,8 +31,6 @@ private:
|
|||
static const size_t kFileExportBlockSize = 0x1000000;
|
||||
|
||||
fnd::IFile* mReader;
|
||||
size_t mOffset;
|
||||
const sKeyset* mKeyset;
|
||||
CliOutputType mCliOutputType;
|
||||
bool mVerify;
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#include "RomfsProcess.h"
|
||||
#include <fnd/SimpleTextOutput.h>
|
||||
#include <fnd/SimpleFile.h>
|
||||
#include <fnd/io.h>
|
||||
#include "OffsetAdjustedIFile.h"
|
||||
#include "RomfsProcess.h"
|
||||
|
||||
void RomfsProcess::printTab(size_t tab) const
|
||||
{
|
||||
|
@ -87,7 +88,7 @@ void RomfsProcess::extractDir(const std::string& path, const sDirectory& dir)
|
|||
|
||||
|
||||
outFile.open(file_path, outFile.Create);
|
||||
mReader->seek(mOffset + dir.file_list[i].offset);
|
||||
mReader->seek(dir.file_list[i].offset);
|
||||
for (size_t j = 0; j < (dir.file_list[i].size / kFileExportBlockSize); j++)
|
||||
{
|
||||
mReader->read(scratch.getBytes(), kFileExportBlockSize);
|
||||
|
@ -186,7 +187,7 @@ void RomfsProcess::importDirectory(uint32_t dir_offset, sDirectory& dir)
|
|||
void RomfsProcess::resolveRomfs()
|
||||
{
|
||||
// read header
|
||||
mReader->read((byte_t*)&mHdr, mOffset, sizeof(nx::sRomfsHeader));
|
||||
mReader->read((byte_t*)&mHdr, 0, sizeof(nx::sRomfsHeader));
|
||||
|
||||
// logic check on the header layout
|
||||
if (validateHeaderLayout(&mHdr) == false)
|
||||
|
@ -196,13 +197,13 @@ void RomfsProcess::resolveRomfs()
|
|||
|
||||
// read directory nodes
|
||||
mDirNodes.alloc(mHdr.sections[nx::romfs::DIR_NODE_TABLE].size.get());
|
||||
mReader->read(mDirNodes.getBytes(), mOffset + mHdr.sections[nx::romfs::DIR_NODE_TABLE].offset.get(), mDirNodes.getSize());
|
||||
mReader->read(mDirNodes.getBytes(), mHdr.sections[nx::romfs::DIR_NODE_TABLE].offset.get(), mDirNodes.getSize());
|
||||
//printf("[RAW DIR NODES]\n");
|
||||
//fnd::SimpleTextOutput::hxdStyleDump(mDirNodes.getBytes(), mDirNodes.getSize());
|
||||
|
||||
// read file nodes
|
||||
mFileNodes.alloc(mHdr.sections[nx::romfs::FILE_NODE_TABLE].size.get());
|
||||
mReader->read(mFileNodes.getBytes(), mOffset + mHdr.sections[nx::romfs::FILE_NODE_TABLE].offset.get(), mFileNodes.getSize());
|
||||
mReader->read(mFileNodes.getBytes(), mHdr.sections[nx::romfs::FILE_NODE_TABLE].offset.get(), mFileNodes.getSize());
|
||||
//printf("[RAW FILE NODES]\n");
|
||||
//fnd::SimpleTextOutput::hxdStyleDump(mFileNodes.getBytes(), mFileNodes.getSize());
|
||||
|
||||
|
@ -223,8 +224,6 @@ void RomfsProcess::resolveRomfs()
|
|||
|
||||
RomfsProcess::RomfsProcess() :
|
||||
mReader(nullptr),
|
||||
mOffset(0),
|
||||
mKeyset(nullptr),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mVerify(false),
|
||||
mExtractPath(),
|
||||
|
@ -239,6 +238,14 @@ RomfsProcess::RomfsProcess() :
|
|||
mRootDir.file_list.clear();
|
||||
}
|
||||
|
||||
RomfsProcess::~RomfsProcess()
|
||||
{
|
||||
if (mReader != nullptr)
|
||||
{
|
||||
delete mReader;
|
||||
}
|
||||
}
|
||||
|
||||
void RomfsProcess::process()
|
||||
{
|
||||
if (mReader == nullptr)
|
||||
|
@ -256,19 +263,9 @@ void RomfsProcess::process()
|
|||
extractFs();
|
||||
}
|
||||
|
||||
void RomfsProcess::setInputFile(fnd::IFile* reader)
|
||||
void RomfsProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size)
|
||||
{
|
||||
mReader = reader;
|
||||
}
|
||||
|
||||
void RomfsProcess::setInputFileOffset(size_t offset)
|
||||
{
|
||||
mOffset = offset;
|
||||
}
|
||||
|
||||
void RomfsProcess::setKeyset(const sKeyset* keyset)
|
||||
{
|
||||
mKeyset = keyset;
|
||||
mReader = new OffsetAdjustedIFile(file, offset, size);
|
||||
}
|
||||
|
||||
void RomfsProcess::setCliOutputMode(CliOutputType type)
|
||||
|
|
|
@ -89,13 +89,12 @@ public:
|
|||
};
|
||||
|
||||
RomfsProcess();
|
||||
~RomfsProcess();
|
||||
|
||||
void process();
|
||||
|
||||
// generic
|
||||
void setInputFile(fnd::IFile* reader);
|
||||
void setInputFileOffset(size_t offset);
|
||||
void setKeyset(const sKeyset* keyset);
|
||||
void setInputFile(fnd::IFile* file, size_t offset, size_t size);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
|
@ -110,8 +109,6 @@ private:
|
|||
static const size_t kFileExportBlockSize = 0x1000000;
|
||||
|
||||
fnd::IFile* mReader;
|
||||
size_t mOffset;
|
||||
const sKeyset* mKeyset;
|
||||
CliOutputType mCliOutputType;
|
||||
bool mVerify;
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ void UserSettings::showHelp()
|
|||
printf("\n General Options:\n");
|
||||
printf(" -d, --dev Use devkit keyset\n");
|
||||
printf(" -k, --keyset Specify keyset file\n");
|
||||
printf(" -t, --type Specify input file type [xci, pfs, romfs, nca, npdm, cmnt]\n");
|
||||
printf(" -t, --type Specify input file type [xci, pfs, romfs, nca, npdm, cnmt]\n");
|
||||
printf(" -y, --verify Verify file\n");
|
||||
printf(" -v, --verbose Verbose output\n");
|
||||
printf(" -q, --quiet Minimal output\n");
|
||||
|
@ -576,8 +576,8 @@ FileType UserSettings::getFileTypeFromString(const std::string& type_str)
|
|||
type = FILE_NCA;
|
||||
else if (str == "npdm")
|
||||
type = FILE_NPDM;
|
||||
else if (str == "cmnt")
|
||||
type = FILE_CMNT;
|
||||
else if (str == "cnmt")
|
||||
type = FILE_CNMT;
|
||||
else
|
||||
type = FILE_INVALID;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "XciProcess.h"
|
||||
#include <fnd/SimpleTextOutput.h>
|
||||
#include <nx/XciUtils.h>
|
||||
#include "OffsetAdjustedIFile.h"
|
||||
#include "XciProcess.h"
|
||||
|
||||
inline const char* getBoolStr(bool isTrue)
|
||||
{
|
||||
|
@ -136,13 +137,12 @@ void XciProcess::processRootPfs()
|
|||
{
|
||||
if (mVerify)
|
||||
{
|
||||
if (validateRegionOfFile(mOffset + mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize(), mHdr.getPartitionFsHash().bytes) == false)
|
||||
if (validateRegionOfFile(mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize(), mHdr.getPartitionFsHash().bytes) == false)
|
||||
{
|
||||
printf("[WARNING] XCI Root HFS0: FAIL (bad hash)\n");
|
||||
}
|
||||
}
|
||||
mRootPfs.setInputFile(mReader);
|
||||
mRootPfs.setInputFileOffset(mOffset + mHdr.getPartitionFsAddress());
|
||||
mRootPfs.setInputFile(mReader, mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize());
|
||||
mRootPfs.setListFs(mListFs);
|
||||
mRootPfs.setVerifyMode(mVerify);
|
||||
mRootPfs.setCliOutputMode(mCliOutputType);
|
||||
|
@ -156,8 +156,7 @@ void XciProcess::processPartitionPfs()
|
|||
for (size_t i = 0; i < rootPartitions.getSize(); i++)
|
||||
{
|
||||
PfsProcess tmp;
|
||||
tmp.setInputFile(mReader);
|
||||
tmp.setInputFileOffset(mOffset + mHdr.getPartitionFsAddress() + rootPartitions[i].offset);
|
||||
tmp.setInputFile(mReader, mHdr.getPartitionFsAddress() + rootPartitions[i].offset, rootPartitions[i].size);
|
||||
tmp.setListFs(mListFs);
|
||||
tmp.setVerifyMode(mVerify);
|
||||
tmp.setCliOutputMode(mCliOutputType);
|
||||
|
@ -174,7 +173,6 @@ void XciProcess::processPartitionPfs()
|
|||
|
||||
XciProcess::XciProcess() :
|
||||
mReader(nullptr),
|
||||
mOffset(0),
|
||||
mKeyset(nullptr),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mVerify(false),
|
||||
|
@ -189,6 +187,14 @@ XciProcess::XciProcess() :
|
|||
mSecurePath.doExtract = false;
|
||||
}
|
||||
|
||||
XciProcess::~XciProcess()
|
||||
{
|
||||
if (mReader != nullptr)
|
||||
{
|
||||
delete mReader;
|
||||
}
|
||||
}
|
||||
|
||||
void XciProcess::process()
|
||||
{
|
||||
fnd::MemoryBlob scratch;
|
||||
|
@ -199,7 +205,7 @@ void XciProcess::process()
|
|||
}
|
||||
|
||||
// read header page
|
||||
mReader->read((byte_t*)&mHdrPage, mOffset, sizeof(nx::sXciHeaderPage));
|
||||
mReader->read((byte_t*)&mHdrPage, 0, sizeof(nx::sXciHeaderPage));
|
||||
|
||||
// allocate memory for and decrypt sXciHeader
|
||||
scratch.alloc(sizeof(nx::sXciHeader));
|
||||
|
@ -227,14 +233,9 @@ void XciProcess::process()
|
|||
processPartitionPfs();
|
||||
}
|
||||
|
||||
void XciProcess::setInputFile(fnd::IFile* reader)
|
||||
void XciProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size)
|
||||
{
|
||||
mReader = reader;
|
||||
}
|
||||
|
||||
void XciProcess::setInputFileOffset(size_t offset)
|
||||
{
|
||||
mOffset = offset;
|
||||
mReader = new OffsetAdjustedIFile(file, offset, size);
|
||||
}
|
||||
|
||||
void XciProcess::setKeyset(const sKeyset* keyset)
|
||||
|
|
|
@ -13,12 +13,12 @@ class XciProcess
|
|||
{
|
||||
public:
|
||||
XciProcess();
|
||||
~XciProcess();
|
||||
|
||||
void process();
|
||||
|
||||
// generic
|
||||
void setInputFile(fnd::IFile* reader);
|
||||
void setInputFileOffset(size_t offset);
|
||||
void setInputFile(fnd::IFile* file, size_t offset, size_t size);
|
||||
void setKeyset(const sKeyset* keyset);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
@ -35,7 +35,6 @@ private:
|
|||
static const size_t kFileExportBlockSize = 0x1000000;
|
||||
|
||||
fnd::IFile* mReader;
|
||||
size_t mOffset;
|
||||
const sKeyset* mKeyset;
|
||||
CliOutputType mCliOutputType;
|
||||
bool mVerify;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "RomfsProcess.h"
|
||||
#include "NcaProcess.h"
|
||||
#include "NpdmProcess.h"
|
||||
#include "CnmtProcess.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
|
@ -21,7 +22,7 @@ int main(int argc, char** argv)
|
|||
{
|
||||
XciProcess xci;
|
||||
|
||||
xci.setInputFile(&inputFile);
|
||||
xci.setInputFile(&inputFile, 0, inputFile.size());
|
||||
|
||||
xci.setKeyset(&user_set.getKeyset());
|
||||
xci.setCliOutputMode(user_set.getCliOutputType());
|
||||
|
@ -41,8 +42,7 @@ int main(int argc, char** argv)
|
|||
{
|
||||
PfsProcess pfs;
|
||||
|
||||
pfs.setInputFile(&inputFile);
|
||||
pfs.setKeyset(&user_set.getKeyset());
|
||||
pfs.setInputFile(&inputFile, 0, inputFile.size());
|
||||
pfs.setCliOutputMode(user_set.getCliOutputType());
|
||||
pfs.setVerifyMode(user_set.isVerifyFile());
|
||||
|
||||
|
@ -56,8 +56,7 @@ int main(int argc, char** argv)
|
|||
{
|
||||
RomfsProcess romfs;
|
||||
|
||||
romfs.setInputFile(&inputFile);
|
||||
romfs.setKeyset(&user_set.getKeyset());
|
||||
romfs.setInputFile(&inputFile, 0, inputFile.size());
|
||||
romfs.setCliOutputMode(user_set.getCliOutputType());
|
||||
romfs.setVerifyMode(user_set.isVerifyFile());
|
||||
|
||||
|
@ -71,7 +70,7 @@ int main(int argc, char** argv)
|
|||
{
|
||||
NcaProcess nca;
|
||||
|
||||
nca.setInputFile(&inputFile);
|
||||
nca.setInputFile(&inputFile, 0, inputFile.size());
|
||||
nca.setKeyset(&user_set.getKeyset());
|
||||
nca.setCliOutputMode(user_set.getCliOutputType());
|
||||
nca.setVerifyMode(user_set.isVerifyFile());
|
||||
|
@ -93,13 +92,23 @@ int main(int argc, char** argv)
|
|||
{
|
||||
NpdmProcess npdm;
|
||||
|
||||
npdm.setInputFile(&inputFile);
|
||||
npdm.setInputFile(&inputFile, 0, inputFile.size());
|
||||
npdm.setKeyset(&user_set.getKeyset());
|
||||
npdm.setCliOutputMode(user_set.getCliOutputType());
|
||||
npdm.setVerifyMode(user_set.isVerifyFile());
|
||||
|
||||
npdm.process();
|
||||
}
|
||||
else if (user_set.getFileType() == FILE_CNMT)
|
||||
{
|
||||
CnmtProcess cnmt;
|
||||
|
||||
cnmt.setInputFile(&inputFile, 0, inputFile.size());
|
||||
cnmt.setCliOutputMode(user_set.getCliOutputType());
|
||||
cnmt.setVerifyMode(user_set.isVerifyFile());
|
||||
|
||||
cnmt.process();
|
||||
}
|
||||
}
|
||||
catch (const fnd::Exception& e) {
|
||||
printf("\n\n%s\n", e.what());
|
||||
|
|
|
@ -17,7 +17,7 @@ enum FileType
|
|||
FILE_ROMFS,
|
||||
FILE_NCA,
|
||||
FILE_NPDM,
|
||||
FILE_CMNT,
|
||||
FILE_CNMT,
|
||||
FILE_INVALID = -1,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue