mirror of
https://github.com/jakcron/nstool
synced 2024-11-15 02:06:40 +00:00
[nstool] Refactored creation and sharing of fnd::IFile ptrs.
This commit is contained in:
parent
97cdaf36ac
commit
08f7f36e68
23 changed files with 282 additions and 310 deletions
|
@ -1,10 +1,5 @@
|
||||||
#include "AesCtrWrappedIFile.h"
|
#include "AesCtrWrappedIFile.h"
|
||||||
|
|
||||||
AesCtrWrappedIFile::AesCtrWrappedIFile(fnd::IFile* file, const crypto::aes::sAes128Key& key, const crypto::aes::sAesIvCtr& ctr) :
|
|
||||||
AesCtrWrappedIFile(file, false, key, ctr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
AesCtrWrappedIFile::AesCtrWrappedIFile(fnd::IFile* file, bool ownIfile, const crypto::aes::sAes128Key& key, const crypto::aes::sAesIvCtr& ctr) :
|
AesCtrWrappedIFile::AesCtrWrappedIFile(fnd::IFile* file, bool ownIfile, const crypto::aes::sAes128Key& key, const crypto::aes::sAesIvCtr& ctr) :
|
||||||
mOwnIFile(ownIfile),
|
mOwnIFile(ownIfile),
|
||||||
mFile(file),
|
mFile(file),
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
class AesCtrWrappedIFile : public fnd::IFile
|
class AesCtrWrappedIFile : public fnd::IFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AesCtrWrappedIFile(fnd::IFile* file, const crypto::aes::sAes128Key& key, const crypto::aes::sAesIvCtr& ctr);
|
|
||||||
AesCtrWrappedIFile(fnd::IFile* file, bool ownIfile, const crypto::aes::sAes128Key& key, const crypto::aes::sAesIvCtr& ctr);
|
AesCtrWrappedIFile(fnd::IFile* file, bool ownIfile, const crypto::aes::sAes128Key& key, const crypto::aes::sAesIvCtr& ctr);
|
||||||
~AesCtrWrappedIFile();
|
~AesCtrWrappedIFile();
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,8 @@ void CnmtProcess::displayCmnt()
|
||||||
}
|
}
|
||||||
|
|
||||||
CnmtProcess::CnmtProcess() :
|
CnmtProcess::CnmtProcess() :
|
||||||
mReader(nullptr),
|
mFile(nullptr),
|
||||||
|
mOwnIFile(false),
|
||||||
mCliOutputType(OUTPUT_NORMAL),
|
mCliOutputType(OUTPUT_NORMAL),
|
||||||
mVerify(false)
|
mVerify(false)
|
||||||
{
|
{
|
||||||
|
@ -151,9 +152,9 @@ CnmtProcess::CnmtProcess() :
|
||||||
|
|
||||||
CnmtProcess::~CnmtProcess()
|
CnmtProcess::~CnmtProcess()
|
||||||
{
|
{
|
||||||
if (mReader != nullptr)
|
if (mOwnIFile)
|
||||||
{
|
{
|
||||||
delete mReader;
|
delete mFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,13 +162,13 @@ void CnmtProcess::process()
|
||||||
{
|
{
|
||||||
fnd::MemoryBlob scratch;
|
fnd::MemoryBlob scratch;
|
||||||
|
|
||||||
if (mReader == nullptr)
|
if (mFile == nullptr)
|
||||||
{
|
{
|
||||||
throw fnd::Exception(kModuleName, "No file reader set.");
|
throw fnd::Exception(kModuleName, "No file reader set.");
|
||||||
}
|
}
|
||||||
|
|
||||||
scratch.alloc(mReader->size());
|
scratch.alloc(mFile->size());
|
||||||
mReader->read(scratch.getBytes(), 0, scratch.getSize());
|
mFile->read(scratch.getBytes(), 0, scratch.getSize());
|
||||||
|
|
||||||
mCnmt.importBinary(scratch.getBytes(), scratch.getSize());
|
mCnmt.importBinary(scratch.getBytes(), scratch.getSize());
|
||||||
|
|
||||||
|
@ -177,9 +178,10 @@ void CnmtProcess::process()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CnmtProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size)
|
void CnmtProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
||||||
{
|
{
|
||||||
mReader = new OffsetAdjustedIFile(file, offset, size);
|
mFile = file;
|
||||||
|
mOwnIFile = ownIFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CnmtProcess::setCliOutputMode(CliOutputType type)
|
void CnmtProcess::setCliOutputMode(CliOutputType type)
|
||||||
|
|
|
@ -14,7 +14,7 @@ public:
|
||||||
|
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
void setInputFile(fnd::IFile* file, size_t offset, size_t size);
|
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||||
void setCliOutputMode(CliOutputType type);
|
void setCliOutputMode(CliOutputType type);
|
||||||
void setVerifyMode(bool verify);
|
void setVerifyMode(bool verify);
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@ public:
|
||||||
private:
|
private:
|
||||||
const std::string kModuleName = "CnmtProcess";
|
const std::string kModuleName = "CnmtProcess";
|
||||||
|
|
||||||
fnd::IFile* mReader;
|
fnd::IFile* mFile;
|
||||||
|
bool mOwnIFile;
|
||||||
CliOutputType mCliOutputType;
|
CliOutputType mCliOutputType;
|
||||||
bool mVerify;
|
bool mVerify;
|
||||||
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <fnd/IFile.h>
|
|
||||||
|
|
||||||
class CopiedIFile : public fnd::IFile
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
inline CopiedIFile(fnd::IFile* file) : mFile(file) {}
|
|
||||||
|
|
||||||
inline size_t size() { return mFile->size(); }
|
|
||||||
inline void seek(size_t offset) { mFile->seek(offset); }
|
|
||||||
inline void read(byte_t* out, size_t len) { mFile->read(out, len); }
|
|
||||||
inline void read(byte_t* out, size_t offset, size_t len) { mFile->read(out, offset, len); }
|
|
||||||
inline void write(const byte_t* out, size_t len) { mFile->write(out, len); }
|
|
||||||
inline void write(const byte_t* out, size_t offset, size_t len) { mFile->write(out, offset, len); }
|
|
||||||
private:
|
|
||||||
fnd::IFile* mFile;
|
|
||||||
};
|
|
|
@ -1,18 +1,7 @@
|
||||||
|
#include "nstool.h"
|
||||||
#include "HashTreeWrappedIFile.h"
|
#include "HashTreeWrappedIFile.h"
|
||||||
#include "CopiedIFile.h"
|
|
||||||
#include "OffsetAdjustedIFile.h"
|
#include "OffsetAdjustedIFile.h"
|
||||||
|
|
||||||
|
|
||||||
HashTreeWrappedIFile::HashTreeWrappedIFile(fnd::IFile* file, const HashTreeMeta& hdr) :
|
|
||||||
mOwnIFile(true),
|
|
||||||
mFile(file),
|
|
||||||
mData(nullptr),
|
|
||||||
mDataHashLayer(),
|
|
||||||
mAlignHashCalcToBlock(false)
|
|
||||||
{
|
|
||||||
initialiseDataLayer(hdr);
|
|
||||||
}
|
|
||||||
|
|
||||||
HashTreeWrappedIFile::HashTreeWrappedIFile(fnd::IFile* file, bool ownIFile, const HashTreeMeta& hdr) :
|
HashTreeWrappedIFile::HashTreeWrappedIFile(fnd::IFile* file, bool ownIFile, const HashTreeMeta& hdr) :
|
||||||
mOwnIFile(ownIFile),
|
mOwnIFile(ownIFile),
|
||||||
mFile(file),
|
mFile(file),
|
||||||
|
@ -156,7 +145,7 @@ void HashTreeWrappedIFile::initialiseDataLayer(const HashTreeMeta& hdr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate reader for data layer
|
// generate reader for data layer
|
||||||
mData = new OffsetAdjustedIFile(mFile, false, hdr.getDataLayer().offset, hdr.getDataLayer().size);
|
mData = new OffsetAdjustedIFile(mFile, SHARED_IFILE, hdr.getDataLayer().offset, hdr.getDataLayer().size);
|
||||||
mDataOffset = 0;
|
mDataOffset = 0;
|
||||||
mDataBlockSize = hdr.getDataLayer().block_size;
|
mDataBlockSize = hdr.getDataLayer().block_size;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
class HashTreeWrappedIFile : public fnd::IFile
|
class HashTreeWrappedIFile : public fnd::IFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HashTreeWrappedIFile(fnd::IFile* file, const HashTreeMeta& hdr);
|
|
||||||
HashTreeWrappedIFile(fnd::IFile* file, bool ownIFile, const HashTreeMeta& hdr);
|
HashTreeWrappedIFile(fnd::IFile* file, bool ownIFile, const HashTreeMeta& hdr);
|
||||||
~HashTreeWrappedIFile();
|
~HashTreeWrappedIFile();
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include "NpdmProcess.h"
|
#include "NpdmProcess.h"
|
||||||
#include "OffsetAdjustedIFile.h"
|
#include "OffsetAdjustedIFile.h"
|
||||||
#include "AesCtrWrappedIFile.h"
|
#include "AesCtrWrappedIFile.h"
|
||||||
#include "CopiedIFile.h"
|
|
||||||
#include "HashTreeWrappedIFile.h"
|
#include "HashTreeWrappedIFile.h"
|
||||||
|
|
||||||
const char* getFormatVersionStr(nx::NcaHeader::FormatVersion format_ver)
|
const char* getFormatVersionStr(nx::NcaHeader::FormatVersion format_ver)
|
||||||
|
@ -222,7 +221,8 @@ const char* getProgramPartitionNameStr(size_t i)
|
||||||
|
|
||||||
|
|
||||||
NcaProcess::NcaProcess() :
|
NcaProcess::NcaProcess() :
|
||||||
mReader(nullptr),
|
mFile(nullptr),
|
||||||
|
mOwnIFile(false),
|
||||||
mKeyset(nullptr),
|
mKeyset(nullptr),
|
||||||
mCliOutputType(OUTPUT_NORMAL),
|
mCliOutputType(OUTPUT_NORMAL),
|
||||||
mVerify(false),
|
mVerify(false),
|
||||||
|
@ -237,9 +237,9 @@ NcaProcess::NcaProcess() :
|
||||||
|
|
||||||
NcaProcess::~NcaProcess()
|
NcaProcess::~NcaProcess()
|
||||||
{
|
{
|
||||||
if (mReader != nullptr)
|
if (mOwnIFile)
|
||||||
{
|
{
|
||||||
delete mReader;
|
delete mFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < nx::nca::kPartitionNum; i++)
|
for (size_t i = 0; i < nx::nca::kPartitionNum; i++)
|
||||||
|
@ -255,13 +255,13 @@ void NcaProcess::process()
|
||||||
{
|
{
|
||||||
fnd::MemoryBlob scratch;
|
fnd::MemoryBlob scratch;
|
||||||
|
|
||||||
if (mReader == nullptr)
|
if (mFile == nullptr)
|
||||||
{
|
{
|
||||||
throw fnd::Exception(kModuleName, "No file reader set.");
|
throw fnd::Exception(kModuleName, "No file reader set.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// read header block
|
// read header block
|
||||||
mReader->read((byte_t*)&mHdrBlock, 0, sizeof(nx::sNcaHeaderBlock));
|
mFile->read((byte_t*)&mHdrBlock, 0, sizeof(nx::sNcaHeaderBlock));
|
||||||
|
|
||||||
// decrypt header block
|
// decrypt header block
|
||||||
nx::NcaUtils::decryptNcaHeader((byte_t*)&mHdrBlock, (byte_t*)&mHdrBlock, mKeyset->nca.header_key);
|
nx::NcaUtils::decryptNcaHeader((byte_t*)&mHdrBlock, (byte_t*)&mHdrBlock, mKeyset->nca.header_key);
|
||||||
|
@ -311,9 +311,10 @@ void NcaProcess::process()
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void NcaProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size)
|
void NcaProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
||||||
{
|
{
|
||||||
mReader = new OffsetAdjustedIFile(file, offset, size);
|
mFile = file;
|
||||||
|
mOwnIFile = ownIFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NcaProcess::setKeyset(const sKeyset* keyset)
|
void NcaProcess::setKeyset(const sKeyset* keyset)
|
||||||
|
@ -539,13 +540,13 @@ void NcaProcess::generatePartitionConfiguration()
|
||||||
// create reader based on encryption type0
|
// create reader based on encryption type0
|
||||||
if (info.enc_type == nx::nca::CRYPT_NONE)
|
if (info.enc_type == nx::nca::CRYPT_NONE)
|
||||||
{
|
{
|
||||||
info.reader = new OffsetAdjustedIFile(mReader, info.offset, info.size);
|
info.reader = new OffsetAdjustedIFile(mFile, SHARED_IFILE, info.offset, info.size);
|
||||||
}
|
}
|
||||||
else if (info.enc_type == nx::nca::CRYPT_AESCTR)
|
else if (info.enc_type == nx::nca::CRYPT_AESCTR)
|
||||||
{
|
{
|
||||||
if (mBodyKeys.aes_ctr.isSet == false)
|
if (mBodyKeys.aes_ctr.isSet == false)
|
||||||
throw fnd::Exception(kModuleName, "AES-CTR Key was not determined");
|
throw fnd::Exception(kModuleName, "AES-CTR Key was not determined");
|
||||||
info.reader = new OffsetAdjustedIFile(new AesCtrWrappedIFile(mReader, mBodyKeys.aes_ctr.var, info.aes_ctr), true, info.offset, info.size);
|
info.reader = new OffsetAdjustedIFile(new AesCtrWrappedIFile(mFile, SHARED_IFILE, mBodyKeys.aes_ctr.var, info.aes_ctr), OWN_IFILE, info.offset, info.size);
|
||||||
}
|
}
|
||||||
else if (info.enc_type == nx::nca::CRYPT_AESXTS || info.enc_type == nx::nca::CRYPT_AESCTREX)
|
else if (info.enc_type == nx::nca::CRYPT_AESXTS || info.enc_type == nx::nca::CRYPT_AESCTREX)
|
||||||
{
|
{
|
||||||
|
@ -565,7 +566,7 @@ void NcaProcess::generatePartitionConfiguration()
|
||||||
{
|
{
|
||||||
fnd::IFile* tmp = info.reader;
|
fnd::IFile* tmp = info.reader;
|
||||||
info.reader = nullptr;
|
info.reader = nullptr;
|
||||||
info.reader = new HashTreeWrappedIFile(tmp, true, info.hash_tree_meta);
|
info.reader = new HashTreeWrappedIFile(tmp, OWN_IFILE, info.hash_tree_meta);
|
||||||
}
|
}
|
||||||
else if (info.hash_type != nx::nca::HASH_NONE)
|
else if (info.hash_type != nx::nca::HASH_NONE)
|
||||||
{
|
{
|
||||||
|
@ -602,7 +603,7 @@ void NcaProcess::validateNcaSignatures()
|
||||||
if (mPartitions[nx::nca::PARTITION_CODE].reader != nullptr)
|
if (mPartitions[nx::nca::PARTITION_CODE].reader != nullptr)
|
||||||
{
|
{
|
||||||
PfsProcess exefs;
|
PfsProcess exefs;
|
||||||
exefs.setInputFile(mPartitions[nx::nca::PARTITION_CODE].reader, 0, mPartitions[nx::nca::PARTITION_CODE].reader->size());
|
exefs.setInputFile(mPartitions[nx::nca::PARTITION_CODE].reader, SHARED_IFILE);
|
||||||
exefs.setCliOutputMode(OUTPUT_MINIMAL);
|
exefs.setCliOutputMode(OUTPUT_MINIMAL);
|
||||||
exefs.process();
|
exefs.process();
|
||||||
|
|
||||||
|
@ -612,7 +613,7 @@ void NcaProcess::validateNcaSignatures()
|
||||||
const nx::PfsHeader::sFile& file = exefs.getPfsHeader().getFileList()[exefs.getPfsHeader().getFileList().getIndexOf(kNpdmExefsPath)];
|
const nx::PfsHeader::sFile& file = exefs.getPfsHeader().getFileList()[exefs.getPfsHeader().getFileList().getIndexOf(kNpdmExefsPath)];
|
||||||
|
|
||||||
NpdmProcess npdm;
|
NpdmProcess npdm;
|
||||||
npdm.setInputFile(mPartitions[nx::nca::PARTITION_CODE].reader, file.offset, file.size);
|
npdm.setInputFile(new OffsetAdjustedIFile(mPartitions[nx::nca::PARTITION_CODE].reader, SHARED_IFILE, file.offset, file.size), OWN_IFILE);
|
||||||
npdm.setCliOutputMode(OUTPUT_MINIMAL);
|
npdm.setCliOutputMode(OUTPUT_MINIMAL);
|
||||||
npdm.process();
|
npdm.process();
|
||||||
|
|
||||||
|
@ -789,7 +790,7 @@ void NcaProcess::processPartitions()
|
||||||
if (partition.format_type == nx::nca::FORMAT_PFS0)
|
if (partition.format_type == nx::nca::FORMAT_PFS0)
|
||||||
{
|
{
|
||||||
PfsProcess pfs;
|
PfsProcess pfs;
|
||||||
pfs.setInputFile(partition.reader, 0, partition.reader->size());
|
pfs.setInputFile(partition.reader, SHARED_IFILE);
|
||||||
pfs.setCliOutputMode(mCliOutputType);
|
pfs.setCliOutputMode(mCliOutputType);
|
||||||
pfs.setListFs(mListFs);
|
pfs.setListFs(mListFs);
|
||||||
if (mHdr.getContentType() == nx::nca::TYPE_PROGRAM)
|
if (mHdr.getContentType() == nx::nca::TYPE_PROGRAM)
|
||||||
|
@ -810,7 +811,7 @@ void NcaProcess::processPartitions()
|
||||||
else if (partition.format_type == nx::nca::FORMAT_ROMFS)
|
else if (partition.format_type == nx::nca::FORMAT_ROMFS)
|
||||||
{
|
{
|
||||||
RomfsProcess romfs;
|
RomfsProcess romfs;
|
||||||
romfs.setInputFile(partition.reader, 0, partition.reader->size());
|
romfs.setInputFile(partition.reader, SHARED_IFILE);
|
||||||
romfs.setCliOutputMode(mCliOutputType);
|
romfs.setCliOutputMode(mCliOutputType);
|
||||||
romfs.setListFs(mListFs);
|
romfs.setListFs(mListFs);
|
||||||
if (mHdr.getContentType() == nx::nca::TYPE_PROGRAM)
|
if (mHdr.getContentType() == nx::nca::TYPE_PROGRAM)
|
||||||
|
|
|
@ -17,7 +17,7 @@ public:
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
void setInputFile(fnd::IFile* file, size_t offset, size_t size);
|
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||||
void setKeyset(const sKeyset* keyset);
|
void setKeyset(const sKeyset* keyset);
|
||||||
void setCliOutputMode(CliOutputType type);
|
void setCliOutputMode(CliOutputType type);
|
||||||
void setVerifyMode(bool verify);
|
void setVerifyMode(bool verify);
|
||||||
|
@ -34,7 +34,8 @@ private:
|
||||||
const std::string kNpdmExefsPath = "main.npdm";
|
const std::string kNpdmExefsPath = "main.npdm";
|
||||||
|
|
||||||
// user options
|
// user options
|
||||||
fnd::IFile* mReader;
|
fnd::IFile* mFile;
|
||||||
|
bool mOwnIFile;
|
||||||
const sKeyset* mKeyset;
|
const sKeyset* mKeyset;
|
||||||
CliOutputType mCliOutputType;
|
CliOutputType mCliOutputType;
|
||||||
bool mVerify;
|
bool mVerify;
|
||||||
|
|
|
@ -1,6 +1,87 @@
|
||||||
#include "OffsetAdjustedIFile.h"
|
|
||||||
#include "NpdmProcess.h"
|
#include "NpdmProcess.h"
|
||||||
|
|
||||||
|
NpdmProcess::NpdmProcess() :
|
||||||
|
mFile(nullptr),
|
||||||
|
mOwnIFile(false),
|
||||||
|
mKeyset(nullptr),
|
||||||
|
mCliOutputType(OUTPUT_NORMAL),
|
||||||
|
mVerify(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NpdmProcess::~NpdmProcess()
|
||||||
|
{
|
||||||
|
if (mOwnIFile)
|
||||||
|
{
|
||||||
|
delete mFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NpdmProcess::process()
|
||||||
|
{
|
||||||
|
fnd::MemoryBlob scratch;
|
||||||
|
|
||||||
|
if (mFile == nullptr)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "No file reader set.");
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch.alloc(mFile->size());
|
||||||
|
mFile->read(scratch.getBytes(), 0, scratch.getSize());
|
||||||
|
|
||||||
|
mNpdm.importBinary(scratch.getBytes(), scratch.getSize());
|
||||||
|
|
||||||
|
if (mVerify)
|
||||||
|
{
|
||||||
|
validateAcidSignature(mNpdm.getAcid());
|
||||||
|
validateAciFromAcid(mNpdm.getAci(), mNpdm.getAcid());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||||
|
{
|
||||||
|
// npdm binary
|
||||||
|
displayNpdmHeader(mNpdm);
|
||||||
|
|
||||||
|
// aci binary
|
||||||
|
displayAciHdr(mNpdm.getAci());
|
||||||
|
displayFac(mNpdm.getAci().getFac());
|
||||||
|
displaySac(mNpdm.getAci().getSac());
|
||||||
|
displayKernelCap(mNpdm.getAci().getKc());
|
||||||
|
|
||||||
|
// acid binary
|
||||||
|
displayAciHdr(mNpdm.getAcid());
|
||||||
|
displayFac(mNpdm.getAcid().getFac());
|
||||||
|
displaySac(mNpdm.getAcid().getSac());
|
||||||
|
displayKernelCap(mNpdm.getAcid().getKc());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NpdmProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
||||||
|
{
|
||||||
|
mFile = file;
|
||||||
|
mOwnIFile = ownIFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NpdmProcess::setKeyset(const sKeyset* keyset)
|
||||||
|
{
|
||||||
|
mKeyset = keyset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NpdmProcess::setCliOutputMode(CliOutputType type)
|
||||||
|
{
|
||||||
|
mCliOutputType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NpdmProcess::setVerifyMode(bool verify)
|
||||||
|
{
|
||||||
|
mVerify = verify;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nx::NpdmBinary& NpdmProcess::getNpdmBinary() const
|
||||||
|
{
|
||||||
|
return mNpdm;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string kInstructionType[2] = { "32Bit", "64Bit" };
|
const std::string kInstructionType[2] = { "32Bit", "64Bit" };
|
||||||
const std::string kProcAddrSpace[4] = { "Unknown", "64Bit", "32Bit", "32Bit no reserved" };
|
const std::string kProcAddrSpace[4] = { "Unknown", "64Bit", "32Bit", "32Bit no reserved" };
|
||||||
const std::string kAciType[2] = { "ACI0", "ACID" };
|
const std::string kAciType[2] = { "ACI0", "ACID" };
|
||||||
|
@ -615,83 +696,3 @@ void NpdmProcess::displayKernelCap(const nx::KcBinary& kern)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NpdmProcess::NpdmProcess() :
|
|
||||||
mReader(nullptr),
|
|
||||||
mKeyset(nullptr),
|
|
||||||
mCliOutputType(OUTPUT_NORMAL),
|
|
||||||
mVerify(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NpdmProcess::~NpdmProcess()
|
|
||||||
{
|
|
||||||
if (mReader != nullptr)
|
|
||||||
{
|
|
||||||
delete mReader;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NpdmProcess::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());
|
|
||||||
|
|
||||||
mNpdm.importBinary(scratch.getBytes(), scratch.getSize());
|
|
||||||
|
|
||||||
if (mVerify)
|
|
||||||
{
|
|
||||||
validateAcidSignature(mNpdm.getAcid());
|
|
||||||
validateAciFromAcid(mNpdm.getAci(), mNpdm.getAcid());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
|
||||||
{
|
|
||||||
// npdm binary
|
|
||||||
displayNpdmHeader(mNpdm);
|
|
||||||
|
|
||||||
// aci binary
|
|
||||||
displayAciHdr(mNpdm.getAci());
|
|
||||||
displayFac(mNpdm.getAci().getFac());
|
|
||||||
displaySac(mNpdm.getAci().getSac());
|
|
||||||
displayKernelCap(mNpdm.getAci().getKc());
|
|
||||||
|
|
||||||
// acid binary
|
|
||||||
displayAciHdr(mNpdm.getAcid());
|
|
||||||
displayFac(mNpdm.getAcid().getFac());
|
|
||||||
displaySac(mNpdm.getAcid().getSac());
|
|
||||||
displayKernelCap(mNpdm.getAcid().getKc());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NpdmProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size)
|
|
||||||
{
|
|
||||||
mReader = new OffsetAdjustedIFile(file, offset, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NpdmProcess::setKeyset(const sKeyset* keyset)
|
|
||||||
{
|
|
||||||
mKeyset = keyset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NpdmProcess::setCliOutputMode(CliOutputType type)
|
|
||||||
{
|
|
||||||
mCliOutputType = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NpdmProcess::setVerifyMode(bool verify)
|
|
||||||
{
|
|
||||||
mVerify = verify;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nx::NpdmBinary& NpdmProcess::getNpdmBinary() const
|
|
||||||
{
|
|
||||||
return mNpdm;
|
|
||||||
}
|
|
|
@ -14,7 +14,7 @@ public:
|
||||||
|
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
void setInputFile(fnd::IFile* file, size_t offset, size_t size);
|
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||||
void setKeyset(const sKeyset* keyset);
|
void setKeyset(const sKeyset* keyset);
|
||||||
void setCliOutputMode(CliOutputType type);
|
void setCliOutputMode(CliOutputType type);
|
||||||
void setVerifyMode(bool verify);
|
void setVerifyMode(bool verify);
|
||||||
|
@ -24,7 +24,8 @@ public:
|
||||||
private:
|
private:
|
||||||
const std::string kModuleName = "NpdmProcess";
|
const std::string kModuleName = "NpdmProcess";
|
||||||
|
|
||||||
fnd::IFile* mReader;
|
fnd::IFile* mFile;
|
||||||
|
bool mOwnIFile;
|
||||||
const sKeyset* mKeyset;
|
const sKeyset* mKeyset;
|
||||||
CliOutputType mCliOutputType;
|
CliOutputType mCliOutputType;
|
||||||
bool mVerify;
|
bool mVerify;
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
#include "NsoProcess.h"
|
#include "NsoProcess.h"
|
||||||
|
|
||||||
NsoProcess::NsoProcess():
|
NsoProcess::NsoProcess():
|
||||||
mReader(nullptr),
|
mFile(nullptr),
|
||||||
|
mOwnIFile(false),
|
||||||
mCliOutputType(OUTPUT_NORMAL),
|
mCliOutputType(OUTPUT_NORMAL),
|
||||||
mVerify(false)
|
mVerify(false)
|
||||||
{
|
{
|
||||||
|
@ -15,15 +16,15 @@ NsoProcess::NsoProcess():
|
||||||
|
|
||||||
NsoProcess::~NsoProcess()
|
NsoProcess::~NsoProcess()
|
||||||
{
|
{
|
||||||
if (mReader != nullptr)
|
if (mOwnIFile)
|
||||||
{
|
{
|
||||||
delete mReader;
|
delete mFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NsoProcess::process()
|
void NsoProcess::process()
|
||||||
{
|
{
|
||||||
if (mReader == nullptr)
|
if (mFile == nullptr)
|
||||||
{
|
{
|
||||||
throw fnd::Exception(kModuleName, "No file reader set.");
|
throw fnd::Exception(kModuleName, "No file reader set.");
|
||||||
}
|
}
|
||||||
|
@ -39,9 +40,10 @@ void NsoProcess::process()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NsoProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size)
|
void NsoProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
||||||
{
|
{
|
||||||
mReader = new OffsetAdjustedIFile(file, offset, size);
|
mFile = file;
|
||||||
|
mOwnIFile = ownIFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NsoProcess::setCliOutputMode(CliOutputType type)
|
void NsoProcess::setCliOutputMode(CliOutputType type)
|
||||||
|
@ -84,17 +86,16 @@ const std::vector<std::string>& NsoProcess::getApiList() const
|
||||||
return mApiList;
|
return mApiList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NsoProcess::importHeader()
|
void NsoProcess::importHeader()
|
||||||
{
|
{
|
||||||
fnd::MemoryBlob scratch;
|
fnd::MemoryBlob scratch;
|
||||||
if (mReader->size() < sizeof(nx::sNsoHeader))
|
if (mFile->size() < sizeof(nx::sNsoHeader))
|
||||||
{
|
{
|
||||||
throw fnd::Exception(kModuleName, "Corrupt NSO file too small");
|
throw fnd::Exception(kModuleName, "Corrupt NSO file too small");
|
||||||
}
|
}
|
||||||
|
|
||||||
scratch.alloc(sizeof(nx::sNsoHeader));
|
scratch.alloc(sizeof(nx::sNsoHeader));
|
||||||
mReader->read(scratch.getBytes(), 0, scratch.getSize());
|
mFile->read(scratch.getBytes(), 0, scratch.getSize());
|
||||||
|
|
||||||
mHdr.importBinary(scratch.getBytes(), scratch.getSize());
|
mHdr.importBinary(scratch.getBytes(), scratch.getSize());
|
||||||
}
|
}
|
||||||
|
@ -109,7 +110,7 @@ void NsoProcess::importCodeSegments()
|
||||||
if (mHdr.getTextSegmentInfo().is_compressed)
|
if (mHdr.getTextSegmentInfo().is_compressed)
|
||||||
{
|
{
|
||||||
scratch.alloc(mHdr.getTextSegmentInfo().file_layout.size);
|
scratch.alloc(mHdr.getTextSegmentInfo().file_layout.size);
|
||||||
mReader->read(scratch.getBytes(), mHdr.getTextSegmentInfo().file_layout.offset, scratch.getSize());
|
mFile->read(scratch.getBytes(), mHdr.getTextSegmentInfo().file_layout.offset, scratch.getSize());
|
||||||
mTextBlob.alloc(mHdr.getTextSegmentInfo().memory_layout.size);
|
mTextBlob.alloc(mHdr.getTextSegmentInfo().memory_layout.size);
|
||||||
compress::lz4::decompressData(scratch.getBytes(), scratch.getSize(), mTextBlob.getBytes(), mTextBlob.getSize(), decompressed_len);
|
compress::lz4::decompressData(scratch.getBytes(), scratch.getSize(), mTextBlob.getBytes(), mTextBlob.getSize(), decompressed_len);
|
||||||
if (decompressed_len != mTextBlob.getSize())
|
if (decompressed_len != mTextBlob.getSize())
|
||||||
|
@ -120,7 +121,7 @@ void NsoProcess::importCodeSegments()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mTextBlob.alloc(mHdr.getTextSegmentInfo().file_layout.size);
|
mTextBlob.alloc(mHdr.getTextSegmentInfo().file_layout.size);
|
||||||
mReader->read(mTextBlob.getBytes(), mHdr.getTextSegmentInfo().file_layout.offset, mTextBlob.getSize());
|
mFile->read(mTextBlob.getBytes(), mHdr.getTextSegmentInfo().file_layout.offset, mTextBlob.getSize());
|
||||||
}
|
}
|
||||||
if (mHdr.getTextSegmentInfo().is_hashed)
|
if (mHdr.getTextSegmentInfo().is_hashed)
|
||||||
{
|
{
|
||||||
|
@ -135,7 +136,7 @@ void NsoProcess::importCodeSegments()
|
||||||
if (mHdr.getRoSegmentInfo().is_compressed)
|
if (mHdr.getRoSegmentInfo().is_compressed)
|
||||||
{
|
{
|
||||||
scratch.alloc(mHdr.getRoSegmentInfo().file_layout.size);
|
scratch.alloc(mHdr.getRoSegmentInfo().file_layout.size);
|
||||||
mReader->read(scratch.getBytes(), mHdr.getRoSegmentInfo().file_layout.offset, scratch.getSize());
|
mFile->read(scratch.getBytes(), mHdr.getRoSegmentInfo().file_layout.offset, scratch.getSize());
|
||||||
mRoBlob.alloc(mHdr.getRoSegmentInfo().memory_layout.size);
|
mRoBlob.alloc(mHdr.getRoSegmentInfo().memory_layout.size);
|
||||||
compress::lz4::decompressData(scratch.getBytes(), scratch.getSize(), mRoBlob.getBytes(), mRoBlob.getSize(), decompressed_len);
|
compress::lz4::decompressData(scratch.getBytes(), scratch.getSize(), mRoBlob.getBytes(), mRoBlob.getSize(), decompressed_len);
|
||||||
if (decompressed_len != mRoBlob.getSize())
|
if (decompressed_len != mRoBlob.getSize())
|
||||||
|
@ -146,7 +147,7 @@ void NsoProcess::importCodeSegments()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mRoBlob.alloc(mHdr.getRoSegmentInfo().file_layout.size);
|
mRoBlob.alloc(mHdr.getRoSegmentInfo().file_layout.size);
|
||||||
mReader->read(mRoBlob.getBytes(), mHdr.getRoSegmentInfo().file_layout.offset, mRoBlob.getSize());
|
mFile->read(mRoBlob.getBytes(), mHdr.getRoSegmentInfo().file_layout.offset, mRoBlob.getSize());
|
||||||
}
|
}
|
||||||
if (mHdr.getRoSegmentInfo().is_hashed)
|
if (mHdr.getRoSegmentInfo().is_hashed)
|
||||||
{
|
{
|
||||||
|
@ -161,7 +162,7 @@ void NsoProcess::importCodeSegments()
|
||||||
if (mHdr.getDataSegmentInfo().is_compressed)
|
if (mHdr.getDataSegmentInfo().is_compressed)
|
||||||
{
|
{
|
||||||
scratch.alloc(mHdr.getDataSegmentInfo().file_layout.size);
|
scratch.alloc(mHdr.getDataSegmentInfo().file_layout.size);
|
||||||
mReader->read(scratch.getBytes(), mHdr.getDataSegmentInfo().file_layout.offset, scratch.getSize());
|
mFile->read(scratch.getBytes(), mHdr.getDataSegmentInfo().file_layout.offset, scratch.getSize());
|
||||||
mDataBlob.alloc(mHdr.getDataSegmentInfo().memory_layout.size);
|
mDataBlob.alloc(mHdr.getDataSegmentInfo().memory_layout.size);
|
||||||
compress::lz4::decompressData(scratch.getBytes(), scratch.getSize(), mDataBlob.getBytes(), mDataBlob.getSize(), decompressed_len);
|
compress::lz4::decompressData(scratch.getBytes(), scratch.getSize(), mDataBlob.getBytes(), mDataBlob.getSize(), decompressed_len);
|
||||||
if (decompressed_len != mDataBlob.getSize())
|
if (decompressed_len != mDataBlob.getSize())
|
||||||
|
@ -172,7 +173,7 @@ void NsoProcess::importCodeSegments()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mDataBlob.alloc(mHdr.getDataSegmentInfo().file_layout.size);
|
mDataBlob.alloc(mHdr.getDataSegmentInfo().file_layout.size);
|
||||||
mReader->read(mDataBlob.getBytes(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.getSize());
|
mFile->read(mDataBlob.getBytes(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.getSize());
|
||||||
}
|
}
|
||||||
if (mHdr.getDataSegmentInfo().is_hashed)
|
if (mHdr.getDataSegmentInfo().is_hashed)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,7 +17,7 @@ public:
|
||||||
|
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
void setInputFile(fnd::IFile* file, size_t offset, size_t size);
|
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||||
void setCliOutputMode(CliOutputType type);
|
void setCliOutputMode(CliOutputType type);
|
||||||
void setVerifyMode(bool verify);
|
void setVerifyMode(bool verify);
|
||||||
|
|
||||||
|
@ -33,7 +33,9 @@ public:
|
||||||
private:
|
private:
|
||||||
const std::string kModuleName = "NsoProcess";
|
const std::string kModuleName = "NsoProcess";
|
||||||
|
|
||||||
fnd::IFile* mReader;
|
fnd::IFile* mFile;
|
||||||
|
bool mOwnIFile;
|
||||||
|
|
||||||
CliOutputType mCliOutputType;
|
CliOutputType mCliOutputType;
|
||||||
bool mVerify;
|
bool mVerify;
|
||||||
sOptional<nx::npdm::InstructionType> mArchType;
|
sOptional<nx::npdm::InstructionType> mArchType;
|
||||||
|
|
|
@ -1,15 +1,5 @@
|
||||||
#include "OffsetAdjustedIFile.h"
|
#include "OffsetAdjustedIFile.h"
|
||||||
|
|
||||||
OffsetAdjustedIFile::OffsetAdjustedIFile(fnd::IFile* file, size_t offset, size_t size) :
|
|
||||||
mOwnIFile(false),
|
|
||||||
mFile(file),
|
|
||||||
mBaseOffset(offset),
|
|
||||||
mCurrentOffset(0),
|
|
||||||
mSize(size)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
OffsetAdjustedIFile::OffsetAdjustedIFile(fnd::IFile* file, bool ownIFile, size_t offset, size_t size) :
|
OffsetAdjustedIFile::OffsetAdjustedIFile(fnd::IFile* file, bool ownIFile, size_t offset, size_t size) :
|
||||||
mOwnIFile(ownIFile),
|
mOwnIFile(ownIFile),
|
||||||
mFile(file),
|
mFile(file),
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
class OffsetAdjustedIFile : public fnd::IFile
|
class OffsetAdjustedIFile : public fnd::IFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OffsetAdjustedIFile(fnd::IFile* file, size_t offset, size_t size);
|
|
||||||
OffsetAdjustedIFile(fnd::IFile* file, bool ownIFile, size_t offset, size_t size);
|
OffsetAdjustedIFile(fnd::IFile* file, bool ownIFile, size_t offset, size_t size);
|
||||||
~OffsetAdjustedIFile();
|
~OffsetAdjustedIFile();
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include <fnd/SimpleFile.h>
|
#include <fnd/SimpleFile.h>
|
||||||
#include <fnd/io.h>
|
#include <fnd/io.h>
|
||||||
#include "OffsetAdjustedIFile.h"
|
|
||||||
#include "PfsProcess.h"
|
#include "PfsProcess.h"
|
||||||
|
|
||||||
PfsProcess::PfsProcess() :
|
PfsProcess::PfsProcess() :
|
||||||
mReader(nullptr),
|
mFile(nullptr),
|
||||||
|
mOwnIFile(false),
|
||||||
mCliOutputType(OUTPUT_NORMAL),
|
mCliOutputType(OUTPUT_NORMAL),
|
||||||
mVerify(false),
|
mVerify(false),
|
||||||
mExtractPath(),
|
mExtractPath(),
|
||||||
|
@ -17,9 +17,9 @@ PfsProcess::PfsProcess() :
|
||||||
|
|
||||||
PfsProcess::~PfsProcess()
|
PfsProcess::~PfsProcess()
|
||||||
{
|
{
|
||||||
if (mReader != nullptr)
|
if (mOwnIFile)
|
||||||
{
|
{
|
||||||
delete mReader;
|
delete mFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,14 +27,14 @@ void PfsProcess::process()
|
||||||
{
|
{
|
||||||
fnd::MemoryBlob scratch;
|
fnd::MemoryBlob scratch;
|
||||||
|
|
||||||
if (mReader == nullptr)
|
if (mFile == nullptr)
|
||||||
{
|
{
|
||||||
throw fnd::Exception(kModuleName, "No file reader set.");
|
throw fnd::Exception(kModuleName, "No file reader set.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// open minimum header to get full header size
|
// open minimum header to get full header size
|
||||||
scratch.alloc(sizeof(nx::sPfsHeader));
|
scratch.alloc(sizeof(nx::sPfsHeader));
|
||||||
mReader->read(scratch.getBytes(), 0, scratch.getSize());
|
mFile->read(scratch.getBytes(), 0, scratch.getSize());
|
||||||
if (validateHeaderMagic(((nx::sPfsHeader*)scratch.getBytes())) == false)
|
if (validateHeaderMagic(((nx::sPfsHeader*)scratch.getBytes())) == false)
|
||||||
{
|
{
|
||||||
throw fnd::Exception(kModuleName, "Corrupt Header");
|
throw fnd::Exception(kModuleName, "Corrupt Header");
|
||||||
|
@ -43,7 +43,7 @@ void PfsProcess::process()
|
||||||
|
|
||||||
// open minimum header to get full header size
|
// open minimum header to get full header size
|
||||||
scratch.alloc(pfsHeaderSize);
|
scratch.alloc(pfsHeaderSize);
|
||||||
mReader->read(scratch.getBytes(), 0, scratch.getSize());
|
mFile->read(scratch.getBytes(), 0, scratch.getSize());
|
||||||
mPfs.importBinary(scratch.getBytes(), scratch.getSize());
|
mPfs.importBinary(scratch.getBytes(), scratch.getSize());
|
||||||
|
|
||||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||||
|
@ -56,9 +56,10 @@ void PfsProcess::process()
|
||||||
extractFs();
|
extractFs();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PfsProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size)
|
void PfsProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
||||||
{
|
{
|
||||||
mReader = new OffsetAdjustedIFile(file, offset, size);
|
mFile = file;
|
||||||
|
mOwnIFile = ownIFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PfsProcess::setCliOutputMode(CliOutputType type)
|
void PfsProcess::setCliOutputMode(CliOutputType type)
|
||||||
|
@ -144,7 +145,7 @@ void PfsProcess::validateHfs()
|
||||||
for (size_t i = 0; i < file.getSize(); i++)
|
for (size_t i = 0; i < file.getSize(); i++)
|
||||||
{
|
{
|
||||||
mCache.alloc(file[i].hash_protected_size);
|
mCache.alloc(file[i].hash_protected_size);
|
||||||
mReader->read(mCache.getBytes(), file[i].offset, file[i].hash_protected_size);
|
mFile->read(mCache.getBytes(), file[i].offset, file[i].hash_protected_size);
|
||||||
crypto::sha::Sha256(mCache.getBytes(), mCache.getSize(), hash.bytes);
|
crypto::sha::Sha256(mCache.getBytes(), mCache.getSize(), hash.bytes);
|
||||||
if (hash != file[i].hash)
|
if (hash != file[i].hash)
|
||||||
{
|
{
|
||||||
|
@ -177,10 +178,10 @@ void PfsProcess::extractFs()
|
||||||
printf("extract=[%s]\n", file_path.c_str());
|
printf("extract=[%s]\n", file_path.c_str());
|
||||||
|
|
||||||
outFile.open(file_path, outFile.Create);
|
outFile.open(file_path, outFile.Create);
|
||||||
mReader->seek(file[i].offset);
|
mFile->seek(file[i].offset);
|
||||||
for (size_t j = 0; j < ((file[i].size / kCacheSize) + ((file[i].size % kCacheSize) != 0)); j++)
|
for (size_t j = 0; j < ((file[i].size / kCacheSize) + ((file[i].size % kCacheSize) != 0)); j++)
|
||||||
{
|
{
|
||||||
mReader->read(mCache.getBytes(), MIN(file[i].size - (kCacheSize * j),kCacheSize));
|
mFile->read(mCache.getBytes(), MIN(file[i].size - (kCacheSize * j),kCacheSize));
|
||||||
outFile.write(mCache.getBytes(), MIN(file[i].size - (kCacheSize * j),kCacheSize));
|
outFile.write(mCache.getBytes(), MIN(file[i].size - (kCacheSize * j),kCacheSize));
|
||||||
}
|
}
|
||||||
outFile.close();
|
outFile.close();
|
||||||
|
|
|
@ -15,7 +15,7 @@ public:
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
void setInputFile(fnd::IFile* file, size_t offset, size_t size);
|
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||||
void setCliOutputMode(CliOutputType type);
|
void setCliOutputMode(CliOutputType type);
|
||||||
void setVerifyMode(bool verify);
|
void setVerifyMode(bool verify);
|
||||||
|
|
||||||
|
@ -30,7 +30,8 @@ private:
|
||||||
const std::string kModuleName = "PfsProcess";
|
const std::string kModuleName = "PfsProcess";
|
||||||
static const size_t kCacheSize = 0x10000;
|
static const size_t kCacheSize = 0x10000;
|
||||||
|
|
||||||
fnd::IFile* mReader;
|
fnd::IFile* mFile;
|
||||||
|
bool mOwnIFile;
|
||||||
CliOutputType mCliOutputType;
|
CliOutputType mCliOutputType;
|
||||||
bool mVerify;
|
bool mVerify;
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#include <fnd/SimpleTextOutput.h>
|
#include <fnd/SimpleTextOutput.h>
|
||||||
#include <fnd/SimpleFile.h>
|
#include <fnd/SimpleFile.h>
|
||||||
#include <fnd/io.h>
|
#include <fnd/io.h>
|
||||||
#include "OffsetAdjustedIFile.h"
|
|
||||||
#include "RomfsProcess.h"
|
#include "RomfsProcess.h"
|
||||||
|
|
||||||
RomfsProcess::RomfsProcess() :
|
RomfsProcess::RomfsProcess() :
|
||||||
mReader(nullptr),
|
mFile(nullptr),
|
||||||
|
mOwnIFile(false),
|
||||||
mCliOutputType(OUTPUT_NORMAL),
|
mCliOutputType(OUTPUT_NORMAL),
|
||||||
mVerify(false),
|
mVerify(false),
|
||||||
mExtractPath(),
|
mExtractPath(),
|
||||||
|
@ -22,15 +22,15 @@ RomfsProcess::RomfsProcess() :
|
||||||
|
|
||||||
RomfsProcess::~RomfsProcess()
|
RomfsProcess::~RomfsProcess()
|
||||||
{
|
{
|
||||||
if (mReader != nullptr)
|
if (mOwnIFile)
|
||||||
{
|
{
|
||||||
delete mReader;
|
delete mFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RomfsProcess::process()
|
void RomfsProcess::process()
|
||||||
{
|
{
|
||||||
if (mReader == nullptr)
|
if (mFile == nullptr)
|
||||||
{
|
{
|
||||||
throw fnd::Exception(kModuleName, "No file reader set.");
|
throw fnd::Exception(kModuleName, "No file reader set.");
|
||||||
}
|
}
|
||||||
|
@ -45,9 +45,10 @@ void RomfsProcess::process()
|
||||||
extractFs();
|
extractFs();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RomfsProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size)
|
void RomfsProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
||||||
{
|
{
|
||||||
mReader = new OffsetAdjustedIFile(file, offset, size);
|
mFile = file;
|
||||||
|
mOwnIFile = ownIFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RomfsProcess::setCliOutputMode(CliOutputType type)
|
void RomfsProcess::setCliOutputMode(CliOutputType type)
|
||||||
|
@ -158,10 +159,10 @@ void RomfsProcess::extractDir(const std::string& path, const sDirectory& dir)
|
||||||
|
|
||||||
|
|
||||||
outFile.open(file_path, outFile.Create);
|
outFile.open(file_path, outFile.Create);
|
||||||
mReader->seek(dir.file_list[i].offset);
|
mFile->seek(dir.file_list[i].offset);
|
||||||
for (size_t j = 0; j < ((dir.file_list[i].size / kCacheSize) + ((dir.file_list[i].size % kCacheSize) != 0)); j++)
|
for (size_t j = 0; j < ((dir.file_list[i].size / kCacheSize) + ((dir.file_list[i].size % kCacheSize) != 0)); j++)
|
||||||
{
|
{
|
||||||
mReader->read(mCache.getBytes(), MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize));
|
mFile->read(mCache.getBytes(), MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize));
|
||||||
outFile.write(mCache.getBytes(), MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize));
|
outFile.write(mCache.getBytes(), MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize));
|
||||||
}
|
}
|
||||||
outFile.close();
|
outFile.close();
|
||||||
|
@ -254,7 +255,7 @@ void RomfsProcess::importDirectory(uint32_t dir_offset, sDirectory& dir)
|
||||||
void RomfsProcess::resolveRomfs()
|
void RomfsProcess::resolveRomfs()
|
||||||
{
|
{
|
||||||
// read header
|
// read header
|
||||||
mReader->read((byte_t*)&mHdr, 0, sizeof(nx::sRomfsHeader));
|
mFile->read((byte_t*)&mHdr, 0, sizeof(nx::sRomfsHeader));
|
||||||
|
|
||||||
// logic check on the header layout
|
// logic check on the header layout
|
||||||
if (validateHeaderLayout(&mHdr) == false)
|
if (validateHeaderLayout(&mHdr) == false)
|
||||||
|
@ -264,13 +265,13 @@ void RomfsProcess::resolveRomfs()
|
||||||
|
|
||||||
// read directory nodes
|
// read directory nodes
|
||||||
mDirNodes.alloc(mHdr.sections[nx::romfs::DIR_NODE_TABLE].size.get());
|
mDirNodes.alloc(mHdr.sections[nx::romfs::DIR_NODE_TABLE].size.get());
|
||||||
mReader->read(mDirNodes.getBytes(), mHdr.sections[nx::romfs::DIR_NODE_TABLE].offset.get(), mDirNodes.getSize());
|
mFile->read(mDirNodes.getBytes(), mHdr.sections[nx::romfs::DIR_NODE_TABLE].offset.get(), mDirNodes.getSize());
|
||||||
//printf("[RAW DIR NODES]\n");
|
//printf("[RAW DIR NODES]\n");
|
||||||
//fnd::SimpleTextOutput::hxdStyleDump(mDirNodes.getBytes(), mDirNodes.getSize());
|
//fnd::SimpleTextOutput::hxdStyleDump(mDirNodes.getBytes(), mDirNodes.getSize());
|
||||||
|
|
||||||
// read file nodes
|
// read file nodes
|
||||||
mFileNodes.alloc(mHdr.sections[nx::romfs::FILE_NODE_TABLE].size.get());
|
mFileNodes.alloc(mHdr.sections[nx::romfs::FILE_NODE_TABLE].size.get());
|
||||||
mReader->read(mFileNodes.getBytes(), mHdr.sections[nx::romfs::FILE_NODE_TABLE].offset.get(), mFileNodes.getSize());
|
mFile->read(mFileNodes.getBytes(), mHdr.sections[nx::romfs::FILE_NODE_TABLE].offset.get(), mFileNodes.getSize());
|
||||||
//printf("[RAW FILE NODES]\n");
|
//printf("[RAW FILE NODES]\n");
|
||||||
//fnd::SimpleTextOutput::hxdStyleDump(mFileNodes.getBytes(), mFileNodes.getSize());
|
//fnd::SimpleTextOutput::hxdStyleDump(mFileNodes.getBytes(), mFileNodes.getSize());
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ public:
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
void setInputFile(fnd::IFile* file, size_t offset, size_t size);
|
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||||
void setCliOutputMode(CliOutputType type);
|
void setCliOutputMode(CliOutputType type);
|
||||||
void setVerifyMode(bool verify);
|
void setVerifyMode(bool verify);
|
||||||
|
|
||||||
|
@ -108,7 +108,8 @@ private:
|
||||||
const std::string kModuleName = "RomfsProcess";
|
const std::string kModuleName = "RomfsProcess";
|
||||||
static const size_t kCacheSize = 0x10000;
|
static const size_t kCacheSize = 0x10000;
|
||||||
|
|
||||||
fnd::IFile* mReader;
|
fnd::IFile* mFile;
|
||||||
|
bool mOwnIFile;
|
||||||
CliOutputType mCliOutputType;
|
CliOutputType mCliOutputType;
|
||||||
bool mVerify;
|
bool mVerify;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,95 @@
|
||||||
#include "OffsetAdjustedIFile.h"
|
#include "OffsetAdjustedIFile.h"
|
||||||
#include "XciProcess.h"
|
#include "XciProcess.h"
|
||||||
|
|
||||||
|
XciProcess::XciProcess() :
|
||||||
|
mFile(nullptr),
|
||||||
|
mOwnIFile(false),
|
||||||
|
mKeyset(nullptr),
|
||||||
|
mCliOutputType(OUTPUT_NORMAL),
|
||||||
|
mVerify(false),
|
||||||
|
mListFs(false),
|
||||||
|
mRootPfs(),
|
||||||
|
mExtractInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
XciProcess::~XciProcess()
|
||||||
|
{
|
||||||
|
if (mOwnIFile)
|
||||||
|
{
|
||||||
|
delete mFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XciProcess::process()
|
||||||
|
{
|
||||||
|
fnd::MemoryBlob scratch;
|
||||||
|
|
||||||
|
if (mFile == nullptr)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "No file reader set.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// read header page
|
||||||
|
mFile->read((byte_t*)&mHdrPage, 0, sizeof(nx::sXciHeaderPage));
|
||||||
|
|
||||||
|
// allocate memory for and decrypt sXciHeader
|
||||||
|
scratch.alloc(sizeof(nx::sXciHeader));
|
||||||
|
nx::XciUtils::decryptXciHeader((const byte_t*)&mHdrPage.header, scratch.getBytes(), mKeyset->xci.header_key.key);
|
||||||
|
|
||||||
|
// validate header signature
|
||||||
|
if (mVerify)
|
||||||
|
{
|
||||||
|
validateXciSignature();
|
||||||
|
}
|
||||||
|
|
||||||
|
// deserialise header
|
||||||
|
mHdr.importBinary(scratch.getBytes(), scratch.getSize());
|
||||||
|
|
||||||
|
// display header
|
||||||
|
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||||
|
{
|
||||||
|
displayHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
// process root partition
|
||||||
|
processRootPfs();
|
||||||
|
|
||||||
|
// process partitions
|
||||||
|
processPartitionPfs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XciProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
||||||
|
{
|
||||||
|
mFile = file;
|
||||||
|
mOwnIFile = ownIFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XciProcess::setKeyset(const sKeyset* keyset)
|
||||||
|
{
|
||||||
|
mKeyset = keyset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XciProcess::setCliOutputMode(CliOutputType type)
|
||||||
|
{
|
||||||
|
mCliOutputType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XciProcess::setVerifyMode(bool verify)
|
||||||
|
{
|
||||||
|
mVerify = verify;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XciProcess::setPartitionForExtract(const std::string& partition_name, const std::string& extract_path)
|
||||||
|
{
|
||||||
|
mExtractInfo.push_back({partition_name, extract_path});
|
||||||
|
}
|
||||||
|
|
||||||
|
void XciProcess::setListFs(bool list_fs)
|
||||||
|
{
|
||||||
|
mListFs = list_fs;
|
||||||
|
}
|
||||||
|
|
||||||
inline const char* getBoolStr(bool isTrue)
|
inline const char* getBoolStr(bool isTrue)
|
||||||
{
|
{
|
||||||
return isTrue? "TRUE" : "FALSE";
|
return isTrue? "TRUE" : "FALSE";
|
||||||
|
@ -51,17 +140,16 @@ inline const char* getCardClockRate(uint32_t acc_ctrl_1)
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XciProcess::displayHeader()
|
void XciProcess::displayHeader()
|
||||||
{
|
{
|
||||||
printf("[XCI HEADER]\n");
|
printf("[XCI HEADER]\n");
|
||||||
printf(" Magic: HEAD\n");
|
printf(" Magic: HEAD\n");
|
||||||
printf(" RomAreaStartPage: 0x%0x", mHdr.getRomAreaStartPage());
|
printf(" RomAreaStartPage: 0x%0x", mHdr.getRomAreaStartPage());
|
||||||
if (mHdr.getRomAreaStartPage() != -1)
|
if (mHdr.getRomAreaStartPage() != (uint32_t)(-1))
|
||||||
printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getRomAreaStartPage()));
|
printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getRomAreaStartPage()));
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" BackupAreaStartPage: 0x%0x", mHdr.getBackupAreaStartPage());
|
printf(" BackupAreaStartPage: 0x%0x", mHdr.getBackupAreaStartPage());
|
||||||
if (mHdr.getBackupAreaStartPage() != -1)
|
if (mHdr.getBackupAreaStartPage() != (uint32_t)(-1))
|
||||||
printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getBackupAreaStartPage()));
|
printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getBackupAreaStartPage()));
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" KekIndex: %d\n", mHdr.getKekIndex());
|
printf(" KekIndex: %d\n", mHdr.getKekIndex());
|
||||||
|
@ -74,7 +162,7 @@ void XciProcess::displayHeader()
|
||||||
printf(" RepairTool: %s\n", getBoolStr(_HAS_BIT(mHdr.getFlags(), nx::xci::FLAG_REPAIR_TOOL)));
|
printf(" RepairTool: %s\n", getBoolStr(_HAS_BIT(mHdr.getFlags(), nx::xci::FLAG_REPAIR_TOOL)));
|
||||||
printf(" PackageId: 0x%" PRIx64 "\n", mHdr.getPackageId());
|
printf(" PackageId: 0x%" PRIx64 "\n", mHdr.getPackageId());
|
||||||
printf(" ValidDataEndPage: 0x%x", mHdr.getValidDataEndPage());
|
printf(" ValidDataEndPage: 0x%x", mHdr.getValidDataEndPage());
|
||||||
if (mHdr.getValidDataEndPage() != -1)
|
if (mHdr.getValidDataEndPage() != (uint32_t)(-1))
|
||||||
printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getValidDataEndPage()));
|
printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getValidDataEndPage()));
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" AesIv: ");
|
printf(" AesIv: ");
|
||||||
|
@ -118,7 +206,7 @@ bool XciProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* t
|
||||||
fnd::MemoryBlob scratch;
|
fnd::MemoryBlob scratch;
|
||||||
crypto::sha::sSha256Hash calc_hash;
|
crypto::sha::sSha256Hash calc_hash;
|
||||||
scratch.alloc(len);
|
scratch.alloc(len);
|
||||||
mReader->read(scratch.getBytes(), offset, len);
|
mFile->read(scratch.getBytes(), offset, len);
|
||||||
crypto::sha::Sha256(scratch.getBytes(), scratch.getSize(), calc_hash.bytes);
|
crypto::sha::Sha256(scratch.getBytes(), scratch.getSize(), calc_hash.bytes);
|
||||||
return calc_hash.compare(test_hash);
|
return calc_hash.compare(test_hash);
|
||||||
}
|
}
|
||||||
|
@ -144,7 +232,7 @@ void XciProcess::processRootPfs()
|
||||||
printf("[WARNING] XCI Root HFS0: FAIL (bad hash)\n");
|
printf("[WARNING] XCI Root HFS0: FAIL (bad hash)\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mRootPfs.setInputFile(mReader, mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize());
|
mRootPfs.setInputFile(new OffsetAdjustedIFile(mFile, SHARED_IFILE, mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize()), OWN_IFILE);
|
||||||
mRootPfs.setListFs(mListFs);
|
mRootPfs.setListFs(mListFs);
|
||||||
mRootPfs.setVerifyMode(mVerify);
|
mRootPfs.setVerifyMode(mVerify);
|
||||||
mRootPfs.setCliOutputMode(mCliOutputType);
|
mRootPfs.setCliOutputMode(mCliOutputType);
|
||||||
|
@ -158,7 +246,7 @@ void XciProcess::processPartitionPfs()
|
||||||
for (size_t i = 0; i < rootPartitions.getSize(); i++)
|
for (size_t i = 0; i < rootPartitions.getSize(); i++)
|
||||||
{
|
{
|
||||||
PfsProcess tmp;
|
PfsProcess tmp;
|
||||||
tmp.setInputFile(mReader, mHdr.getPartitionFsAddress() + rootPartitions[i].offset, rootPartitions[i].size);
|
tmp.setInputFile(new OffsetAdjustedIFile(mFile, SHARED_IFILE, mHdr.getPartitionFsAddress() + rootPartitions[i].offset, rootPartitions[i].size), OWN_IFILE);
|
||||||
tmp.setListFs(mListFs);
|
tmp.setListFs(mListFs);
|
||||||
tmp.setVerifyMode(mVerify);
|
tmp.setVerifyMode(mVerify);
|
||||||
tmp.setCliOutputMode(mCliOutputType);
|
tmp.setCliOutputMode(mCliOutputType);
|
||||||
|
@ -172,91 +260,4 @@ void XciProcess::processPartitionPfs()
|
||||||
}
|
}
|
||||||
tmp.process();
|
tmp.process();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XciProcess::XciProcess() :
|
|
||||||
mReader(nullptr),
|
|
||||||
mKeyset(nullptr),
|
|
||||||
mCliOutputType(OUTPUT_NORMAL),
|
|
||||||
mVerify(false),
|
|
||||||
mListFs(false),
|
|
||||||
mRootPfs(),
|
|
||||||
mExtractInfo()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
XciProcess::~XciProcess()
|
|
||||||
{
|
|
||||||
if (mReader != nullptr)
|
|
||||||
{
|
|
||||||
delete mReader;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void XciProcess::process()
|
|
||||||
{
|
|
||||||
fnd::MemoryBlob scratch;
|
|
||||||
|
|
||||||
if (mReader == nullptr)
|
|
||||||
{
|
|
||||||
throw fnd::Exception(kModuleName, "No file reader set.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// read header page
|
|
||||||
mReader->read((byte_t*)&mHdrPage, 0, sizeof(nx::sXciHeaderPage));
|
|
||||||
|
|
||||||
// allocate memory for and decrypt sXciHeader
|
|
||||||
scratch.alloc(sizeof(nx::sXciHeader));
|
|
||||||
nx::XciUtils::decryptXciHeader((const byte_t*)&mHdrPage.header, scratch.getBytes(), mKeyset->xci.header_key.key);
|
|
||||||
|
|
||||||
// validate header signature
|
|
||||||
if (mVerify)
|
|
||||||
{
|
|
||||||
validateXciSignature();
|
|
||||||
}
|
|
||||||
|
|
||||||
// deserialise header
|
|
||||||
mHdr.importBinary(scratch.getBytes(), scratch.getSize());
|
|
||||||
|
|
||||||
// display header
|
|
||||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
|
||||||
{
|
|
||||||
displayHeader();
|
|
||||||
}
|
|
||||||
|
|
||||||
// process root partition
|
|
||||||
processRootPfs();
|
|
||||||
|
|
||||||
// process partitions
|
|
||||||
processPartitionPfs();
|
|
||||||
}
|
|
||||||
|
|
||||||
void XciProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size)
|
|
||||||
{
|
|
||||||
mReader = new OffsetAdjustedIFile(file, offset, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void XciProcess::setKeyset(const sKeyset* keyset)
|
|
||||||
{
|
|
||||||
mKeyset = keyset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void XciProcess::setCliOutputMode(CliOutputType type)
|
|
||||||
{
|
|
||||||
mCliOutputType = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void XciProcess::setVerifyMode(bool verify)
|
|
||||||
{
|
|
||||||
mVerify = verify;
|
|
||||||
}
|
|
||||||
|
|
||||||
void XciProcess::setPartitionForExtract(const std::string& partition_name, const std::string& extract_path)
|
|
||||||
{
|
|
||||||
mExtractInfo.push_back({partition_name, extract_path});
|
|
||||||
}
|
|
||||||
|
|
||||||
void XciProcess::setListFs(bool list_fs)
|
|
||||||
{
|
|
||||||
mListFs = list_fs;
|
|
||||||
}
|
|
|
@ -18,7 +18,7 @@ public:
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
void setInputFile(fnd::IFile* file, size_t offset, size_t size);
|
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||||
void setKeyset(const sKeyset* keyset);
|
void setKeyset(const sKeyset* keyset);
|
||||||
void setCliOutputMode(CliOutputType type);
|
void setCliOutputMode(CliOutputType type);
|
||||||
void setVerifyMode(bool verify);
|
void setVerifyMode(bool verify);
|
||||||
|
@ -32,7 +32,8 @@ private:
|
||||||
const std::string kXciMountPointName = "gamecard:/";
|
const std::string kXciMountPointName = "gamecard:/";
|
||||||
static const size_t kFileExportBlockSize = 0x1000000;
|
static const size_t kFileExportBlockSize = 0x1000000;
|
||||||
|
|
||||||
fnd::IFile* mReader;
|
fnd::IFile* mFile;
|
||||||
|
bool mOwnIFile;
|
||||||
const sKeyset* mKeyset;
|
const sKeyset* mKeyset;
|
||||||
CliOutputType mCliOutputType;
|
CliOutputType mCliOutputType;
|
||||||
bool mVerify;
|
bool mVerify;
|
||||||
|
|
|
@ -15,14 +15,11 @@ int main(int argc, char** argv)
|
||||||
try {
|
try {
|
||||||
user_set.parseCmdArgs(argc, argv);
|
user_set.parseCmdArgs(argc, argv);
|
||||||
|
|
||||||
fnd::SimpleFile inputFile;
|
|
||||||
inputFile.open(user_set.getInputPath(), inputFile.Read);
|
|
||||||
|
|
||||||
if (user_set.getFileType() == FILE_XCI)
|
if (user_set.getFileType() == FILE_XCI)
|
||||||
{
|
{
|
||||||
XciProcess xci;
|
XciProcess xci;
|
||||||
|
|
||||||
xci.setInputFile(&inputFile, 0, inputFile.size());
|
xci.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||||
|
|
||||||
xci.setKeyset(&user_set.getKeyset());
|
xci.setKeyset(&user_set.getKeyset());
|
||||||
xci.setCliOutputMode(user_set.getCliOutputType());
|
xci.setCliOutputMode(user_set.getCliOutputType());
|
||||||
|
@ -44,7 +41,7 @@ int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
PfsProcess pfs;
|
PfsProcess pfs;
|
||||||
|
|
||||||
pfs.setInputFile(&inputFile, 0, inputFile.size());
|
pfs.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||||
pfs.setCliOutputMode(user_set.getCliOutputType());
|
pfs.setCliOutputMode(user_set.getCliOutputType());
|
||||||
pfs.setVerifyMode(user_set.isVerifyFile());
|
pfs.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
|
@ -58,7 +55,7 @@ int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
RomfsProcess romfs;
|
RomfsProcess romfs;
|
||||||
|
|
||||||
romfs.setInputFile(&inputFile, 0, inputFile.size());
|
romfs.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||||
romfs.setCliOutputMode(user_set.getCliOutputType());
|
romfs.setCliOutputMode(user_set.getCliOutputType());
|
||||||
romfs.setVerifyMode(user_set.isVerifyFile());
|
romfs.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
|
@ -72,7 +69,7 @@ int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
NcaProcess nca;
|
NcaProcess nca;
|
||||||
|
|
||||||
nca.setInputFile(&inputFile, 0, inputFile.size());
|
nca.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||||
nca.setKeyset(&user_set.getKeyset());
|
nca.setKeyset(&user_set.getKeyset());
|
||||||
nca.setCliOutputMode(user_set.getCliOutputType());
|
nca.setCliOutputMode(user_set.getCliOutputType());
|
||||||
nca.setVerifyMode(user_set.isVerifyFile());
|
nca.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
@ -94,7 +91,7 @@ int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
NpdmProcess npdm;
|
NpdmProcess npdm;
|
||||||
|
|
||||||
npdm.setInputFile(&inputFile, 0, inputFile.size());
|
npdm.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||||
npdm.setKeyset(&user_set.getKeyset());
|
npdm.setKeyset(&user_set.getKeyset());
|
||||||
npdm.setCliOutputMode(user_set.getCliOutputType());
|
npdm.setCliOutputMode(user_set.getCliOutputType());
|
||||||
npdm.setVerifyMode(user_set.isVerifyFile());
|
npdm.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
@ -105,7 +102,7 @@ int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
CnmtProcess cnmt;
|
CnmtProcess cnmt;
|
||||||
|
|
||||||
cnmt.setInputFile(&inputFile, 0, inputFile.size());
|
cnmt.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||||
cnmt.setCliOutputMode(user_set.getCliOutputType());
|
cnmt.setCliOutputMode(user_set.getCliOutputType());
|
||||||
cnmt.setVerifyMode(user_set.isVerifyFile());
|
cnmt.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
|
@ -115,7 +112,7 @@ int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
NsoProcess nso;
|
NsoProcess nso;
|
||||||
|
|
||||||
nso.setInputFile(&inputFile, 0, inputFile.size());
|
nso.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||||
nso.setCliOutputMode(user_set.getCliOutputType());
|
nso.setCliOutputMode(user_set.getCliOutputType());
|
||||||
nso.setVerifyMode(user_set.isVerifyFile());
|
nso.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,11 @@
|
||||||
static const size_t kMasterKeyNum = 0x20;
|
static const size_t kMasterKeyNum = 0x20;
|
||||||
static const size_t kNcaKeakNum = nx::nca::kKeyAreaEncryptionKeyNum;
|
static const size_t kNcaKeakNum = nx::nca::kKeyAreaEncryptionKeyNum;
|
||||||
|
|
||||||
|
enum IFileOwnershipMode
|
||||||
|
{
|
||||||
|
SHARED_IFILE = false,
|
||||||
|
OWN_IFILE = true
|
||||||
|
};
|
||||||
|
|
||||||
enum FileType
|
enum FileType
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue