mirror of
https://github.com/jakcron/nstool
synced 2024-11-15 02:06:40 +00:00
Merge pull request #14 from jakcron/xci-development
[nx|nstool] Added support for xci logo partition.
This commit is contained in:
commit
f13b4ec2a4
8 changed files with 93 additions and 111 deletions
|
@ -23,6 +23,11 @@ namespace nx
|
||||||
static const uint32_t kCertAreaPageCount = 64;
|
static const uint32_t kCertAreaPageCount = 64;
|
||||||
static const uint32_t kNormalAreaStartPageAddress = kReservedAreaPageCount + kCertAreaPageCount + kCardHeaderPageCount + kCardKeyAreaPageCount;
|
static const uint32_t kNormalAreaStartPageAddress = kReservedAreaPageCount + kCertAreaPageCount + kCardHeaderPageCount + kCardKeyAreaPageCount;
|
||||||
|
|
||||||
|
const std::string kUpdatePartitionStr = "update";
|
||||||
|
const std::string kNormalPartitionStr = "normal";
|
||||||
|
const std::string kSecurePartitionStr = "secure";
|
||||||
|
const std::string kLogoPartitionStr = "logo";
|
||||||
|
|
||||||
|
|
||||||
enum KekIndex
|
enum KekIndex
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fnd/types.h>
|
#include <fnd/types.h>
|
||||||
#include <fnd/IFile.h>
|
#include <fnd/IFile.h>
|
||||||
|
#include <nx/npdm.h>
|
||||||
#include <nx/NsoHeader.h>
|
#include <nx/NsoHeader.h>
|
||||||
|
|
||||||
#include "nstool.h"
|
#include "nstool.h"
|
||||||
|
|
|
@ -48,6 +48,7 @@ void UserSettings::showHelp()
|
||||||
printf(" --listfs Print file system in embedded partitions\n");
|
printf(" --listfs Print file system in embedded partitions\n");
|
||||||
printf(" --update Extract \"update\" partition to directory\n");
|
printf(" --update Extract \"update\" partition to directory\n");
|
||||||
printf(" --normal Extract \"normal\" partition to directory\n");
|
printf(" --normal Extract \"normal\" partition to directory\n");
|
||||||
|
printf(" --logo Extract \"logo\" partition to directory\n");
|
||||||
printf(" --secure Extract \"secure\" partition to directory\n");
|
printf(" --secure Extract \"secure\" partition to directory\n");
|
||||||
printf("\n PFS0/HFS0 (PartitionFs), RomFs, NSP (Ninendo Submission Package)\n");
|
printf("\n PFS0/HFS0 (PartitionFs), RomFs, NSP (Ninendo Submission Package)\n");
|
||||||
printf(" nstool [--listfs] [--fsdir <dir>] <file>\n");
|
printf(" nstool [--listfs] [--fsdir <dir>] <file>\n");
|
||||||
|
@ -103,19 +104,24 @@ const sOptional<nx::npdm::InstructionType>& UserSettings::getArchType() const
|
||||||
return mArchType;
|
return mArchType;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sOptional<std::string>& UserSettings::getUpdatePath() const
|
const sOptional<std::string>& UserSettings::getXciUpdatePath() const
|
||||||
{
|
{
|
||||||
return mUpdatePath;
|
return mXciUpdatePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sOptional<std::string>& UserSettings::getNormalPath() const
|
const sOptional<std::string>& UserSettings::getXciNormalPath() const
|
||||||
{
|
{
|
||||||
return mNormalPath;
|
return mXciNormalPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sOptional<std::string>& UserSettings::getSecurePath() const
|
const sOptional<std::string>& UserSettings::getXciSecurePath() const
|
||||||
{
|
{
|
||||||
return mSecurePath;
|
return mXciSecurePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sOptional<std::string>& UserSettings::getXciLogoPath() const
|
||||||
|
{
|
||||||
|
return mXciLogoPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sOptional<std::string>& UserSettings::getFsPath() const
|
const sOptional<std::string>& UserSettings::getFsPath() const
|
||||||
|
@ -123,24 +129,24 @@ const sOptional<std::string>& UserSettings::getFsPath() const
|
||||||
return mFsPath;
|
return mFsPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sOptional<std::string>& UserSettings::getPart0Path() const
|
const sOptional<std::string>& UserSettings::getNcaPart0Path() const
|
||||||
{
|
{
|
||||||
return mPart0Path;
|
return mNcaPart0Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sOptional<std::string>& UserSettings::getPart1Path() const
|
const sOptional<std::string>& UserSettings::getNcaPart1Path() const
|
||||||
{
|
{
|
||||||
return mPart1Path;
|
return mNcaPart1Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sOptional<std::string>& UserSettings::getPart2Path() const
|
const sOptional<std::string>& UserSettings::getNcaPart2Path() const
|
||||||
{
|
{
|
||||||
return mPart2Path;
|
return mNcaPart2Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sOptional<std::string>& UserSettings::getPart3Path() const
|
const sOptional<std::string>& UserSettings::getNcaPart3Path() const
|
||||||
{
|
{
|
||||||
return mPart3Path;
|
return mNcaPart3Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -160,7 +166,6 @@ void UserSettings::populateCmdArgs(int argc, char** argv, sCmdArgs& cmd_args)
|
||||||
throw fnd::Exception(kModuleName, "Not enough arguments.");
|
throw fnd::Exception(kModuleName, "Not enough arguments.");
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_args.clear();
|
|
||||||
cmd_args.input_path = args.back();
|
cmd_args.input_path = args.back();
|
||||||
|
|
||||||
for (size_t i = 1; i < args.size(); i++)
|
for (size_t i = 1; i < args.size(); i++)
|
||||||
|
@ -236,6 +241,12 @@ void UserSettings::populateCmdArgs(int argc, char** argv, sCmdArgs& cmd_args)
|
||||||
cmd_args.secure_path = args[i+1];
|
cmd_args.secure_path = args[i+1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (args[i] == "--logo")
|
||||||
|
{
|
||||||
|
if (!hasParamter) throw fnd::Exception(kModuleName, args[i] + " requries a parameter.");
|
||||||
|
cmd_args.logo_path = args[i+1];
|
||||||
|
}
|
||||||
|
|
||||||
else if (args[i] == "--fsdir")
|
else if (args[i] == "--fsdir")
|
||||||
{
|
{
|
||||||
if (!hasParamter) throw fnd::Exception(kModuleName, args[i] + " requries a parameter.");
|
if (!hasParamter) throw fnd::Exception(kModuleName, args[i] + " requries a parameter.");
|
||||||
|
@ -530,20 +541,20 @@ void UserSettings::populateUserSettings(sCmdArgs& args)
|
||||||
mInputPath = *args.input_path;
|
mInputPath = *args.input_path;
|
||||||
mVerifyFile = args.verify_file.isSet;
|
mVerifyFile = args.verify_file.isSet;
|
||||||
mListFs = args.list_fs.isSet;
|
mListFs = args.list_fs.isSet;
|
||||||
mUpdatePath = args.update_path;
|
mXciUpdatePath = args.update_path;
|
||||||
mNormalPath = args.normal_path;
|
mXciNormalPath = args.normal_path;
|
||||||
mSecurePath = args.secure_path;
|
mXciSecurePath = args.secure_path;
|
||||||
|
mXciLogoPath = args.logo_path;
|
||||||
|
|
||||||
mFsPath = args.fs_path;
|
mFsPath = args.fs_path;
|
||||||
mPart0Path = args.part0_path;
|
mNcaPart0Path = args.part0_path;
|
||||||
mPart1Path = args.part1_path;
|
mNcaPart1Path = args.part1_path;
|
||||||
mPart2Path = args.part2_path;
|
mNcaPart2Path = args.part2_path;
|
||||||
mPart3Path = args.part3_path;
|
mNcaPart3Path = args.part3_path;
|
||||||
|
|
||||||
// determine the architecture type for NSO
|
// determine the architecture type for NSO
|
||||||
if (args.arch_type.isSet)
|
if (args.arch_type.isSet)
|
||||||
mArchType = getInstructionTypeFromString(*args.arch_type);
|
mArchType = getInstructionTypeFromString(*args.arch_type);
|
||||||
else
|
|
||||||
mArchType.isSet = false;
|
|
||||||
|
|
||||||
// determine output path
|
// determine output path
|
||||||
if (args.verbose_output.isSet)
|
if (args.verbose_output.isSet)
|
||||||
|
|
|
@ -24,20 +24,22 @@ public:
|
||||||
const sOptional<nx::npdm::InstructionType>& getArchType() const;
|
const sOptional<nx::npdm::InstructionType>& getArchType() const;
|
||||||
|
|
||||||
// specialised paths
|
// specialised paths
|
||||||
const sOptional<std::string>& getUpdatePath() const;
|
const sOptional<std::string>& getXciUpdatePath() const;
|
||||||
const sOptional<std::string>& getNormalPath() const;
|
const sOptional<std::string>& getXciNormalPath() const;
|
||||||
const sOptional<std::string>& getSecurePath() const;
|
const sOptional<std::string>& getXciSecurePath() const;
|
||||||
|
const sOptional<std::string>& getXciLogoPath() const;
|
||||||
const sOptional<std::string>& getFsPath() const;
|
const sOptional<std::string>& getFsPath() const;
|
||||||
const sOptional<std::string>& getPart0Path() const;
|
const sOptional<std::string>& getNcaPart0Path() const;
|
||||||
const sOptional<std::string>& getPart1Path() const;
|
const sOptional<std::string>& getNcaPart1Path() const;
|
||||||
const sOptional<std::string>& getPart2Path() const;
|
const sOptional<std::string>& getNcaPart2Path() const;
|
||||||
const sOptional<std::string>& getPart3Path() const;
|
const sOptional<std::string>& getNcaPart3Path() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string kModuleName = "UserSettings";
|
const std::string kModuleName = "UserSettings";
|
||||||
|
|
||||||
struct sCmdArgs
|
struct sCmdArgs
|
||||||
{
|
{
|
||||||
|
sCmdArgs() {}
|
||||||
sOptional<std::string> input_path;
|
sOptional<std::string> input_path;
|
||||||
sOptional<bool> devkit_keys;
|
sOptional<bool> devkit_keys;
|
||||||
sOptional<std::string> keyset_path;
|
sOptional<std::string> keyset_path;
|
||||||
|
@ -49,6 +51,7 @@ private:
|
||||||
sOptional<std::string> update_path;
|
sOptional<std::string> update_path;
|
||||||
sOptional<std::string> normal_path;
|
sOptional<std::string> normal_path;
|
||||||
sOptional<std::string> secure_path;
|
sOptional<std::string> secure_path;
|
||||||
|
sOptional<std::string> logo_path;
|
||||||
sOptional<std::string> fs_path;
|
sOptional<std::string> fs_path;
|
||||||
sOptional<std::string> nca_titlekey;
|
sOptional<std::string> nca_titlekey;
|
||||||
sOptional<std::string> nca_bodykey;
|
sOptional<std::string> nca_bodykey;
|
||||||
|
@ -57,29 +60,6 @@ private:
|
||||||
sOptional<std::string> part2_path;
|
sOptional<std::string> part2_path;
|
||||||
sOptional<std::string> part3_path;
|
sOptional<std::string> part3_path;
|
||||||
sOptional<std::string> arch_type;
|
sOptional<std::string> arch_type;
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
input_path.isSet = false;
|
|
||||||
devkit_keys.isSet = false;
|
|
||||||
keyset_path.isSet = false;
|
|
||||||
file_type.isSet = false;
|
|
||||||
verify_file.isSet = false;
|
|
||||||
verbose_output.isSet = false;
|
|
||||||
minimal_output.isSet = false;
|
|
||||||
list_fs.isSet = false;
|
|
||||||
update_path.isSet = false;
|
|
||||||
normal_path.isSet = false;
|
|
||||||
secure_path.isSet = false;
|
|
||||||
fs_path.isSet = false;
|
|
||||||
nca_titlekey.isSet = false;
|
|
||||||
nca_bodykey.isSet = false;
|
|
||||||
part0_path.isSet = false;
|
|
||||||
part1_path.isSet = false;
|
|
||||||
part2_path.isSet = false;
|
|
||||||
part3_path.isSet = false;
|
|
||||||
arch_type.isSet = false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string mInputPath;
|
std::string mInputPath;
|
||||||
|
@ -89,15 +69,16 @@ private:
|
||||||
CliOutputType mOutputType;
|
CliOutputType mOutputType;
|
||||||
|
|
||||||
bool mListFs;
|
bool mListFs;
|
||||||
sOptional<std::string> mUpdatePath;
|
sOptional<std::string> mXciUpdatePath;
|
||||||
sOptional<std::string> mNormalPath;
|
sOptional<std::string> mXciNormalPath;
|
||||||
sOptional<std::string> mSecurePath;
|
sOptional<std::string> mXciSecurePath;
|
||||||
|
sOptional<std::string> mXciLogoPath;
|
||||||
sOptional<std::string> mFsPath;
|
sOptional<std::string> mFsPath;
|
||||||
|
|
||||||
sOptional<std::string> mPart0Path;
|
sOptional<std::string> mNcaPart0Path;
|
||||||
sOptional<std::string> mPart1Path;
|
sOptional<std::string> mNcaPart1Path;
|
||||||
sOptional<std::string> mPart2Path;
|
sOptional<std::string> mNcaPart2Path;
|
||||||
sOptional<std::string> mPart3Path;
|
sOptional<std::string> mNcaPart3Path;
|
||||||
|
|
||||||
sOptional<nx::npdm::InstructionType> mArchType;
|
sOptional<nx::npdm::InstructionType> mArchType;
|
||||||
|
|
||||||
|
|
|
@ -163,12 +163,13 @@ void XciProcess::processPartitionPfs()
|
||||||
tmp.setVerifyMode(mVerify);
|
tmp.setVerifyMode(mVerify);
|
||||||
tmp.setCliOutputMode(mCliOutputType);
|
tmp.setCliOutputMode(mCliOutputType);
|
||||||
tmp.setMountPointName(kXciMountPointName + rootPartitions[i].name);
|
tmp.setMountPointName(kXciMountPointName + rootPartitions[i].name);
|
||||||
if (mUpdatePath.doExtract && rootPartitions[i].name == "update")
|
for (size_t j = 0; j < mExtractInfo.size(); j++)
|
||||||
tmp.setExtractPath(mUpdatePath.path);
|
{
|
||||||
if (mNormalPath.doExtract && rootPartitions[i].name == "normal")
|
if (mExtractInfo[j].partition_name == rootPartitions[i].name)
|
||||||
tmp.setExtractPath(mNormalPath.path);
|
{
|
||||||
if (mSecurePath.doExtract && rootPartitions[i].name == "secure")
|
tmp.setExtractPath(mExtractInfo[j].extract_path);
|
||||||
tmp.setExtractPath(mSecurePath.path);
|
}
|
||||||
|
}
|
||||||
tmp.process();
|
tmp.process();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,13 +181,8 @@ XciProcess::XciProcess() :
|
||||||
mVerify(false),
|
mVerify(false),
|
||||||
mListFs(false),
|
mListFs(false),
|
||||||
mRootPfs(),
|
mRootPfs(),
|
||||||
mUpdatePfs(),
|
mExtractInfo()
|
||||||
mNormalPfs(),
|
|
||||||
mSecurePfs()
|
|
||||||
{
|
{
|
||||||
mUpdatePath.doExtract = false;
|
|
||||||
mNormalPath.doExtract = false;
|
|
||||||
mSecurePath.doExtract = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XciProcess::~XciProcess()
|
XciProcess::~XciProcess()
|
||||||
|
@ -255,22 +251,9 @@ void XciProcess::setVerifyMode(bool verify)
|
||||||
mVerify = verify;
|
mVerify = verify;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XciProcess::setUpdateExtractPath(const std::string& path)
|
void XciProcess::setPartitionForExtract(const std::string& partition_name, const std::string& extract_path)
|
||||||
{
|
{
|
||||||
mUpdatePath.path = path;
|
mExtractInfo.push_back({partition_name, extract_path});
|
||||||
mUpdatePath.doExtract = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void XciProcess::setNormalExtractPath(const std::string& path)
|
|
||||||
{
|
|
||||||
mNormalPath.path = path;
|
|
||||||
mNormalPath.doExtract = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void XciProcess::setSecureExtractPath(const std::string& path)
|
|
||||||
{
|
|
||||||
mSecurePath.path = path;
|
|
||||||
mSecurePath.doExtract = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void XciProcess::setListFs(bool list_fs)
|
void XciProcess::setListFs(bool list_fs)
|
||||||
|
|
|
@ -24,9 +24,7 @@ public:
|
||||||
void setVerifyMode(bool verify);
|
void setVerifyMode(bool verify);
|
||||||
|
|
||||||
// xci specific
|
// xci specific
|
||||||
void setUpdateExtractPath(const std::string& path);
|
void setPartitionForExtract(const std::string& partition_name, const std::string& extract_path);
|
||||||
void setNormalExtractPath(const std::string& path);
|
|
||||||
void setSecureExtractPath(const std::string& path);
|
|
||||||
void setListFs(bool list_fs);
|
void setListFs(bool list_fs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -39,17 +37,18 @@ private:
|
||||||
CliOutputType mCliOutputType;
|
CliOutputType mCliOutputType;
|
||||||
bool mVerify;
|
bool mVerify;
|
||||||
|
|
||||||
struct sExtract
|
struct sExtractInfo
|
||||||
{
|
{
|
||||||
std::string path;
|
std::string partition_name;
|
||||||
bool doExtract;
|
std::string extract_path;
|
||||||
} mUpdatePath, mNormalPath, mSecurePath;
|
};
|
||||||
|
|
||||||
bool mListFs;
|
bool mListFs;
|
||||||
|
|
||||||
nx::sXciHeaderPage mHdrPage;
|
nx::sXciHeaderPage mHdrPage;
|
||||||
nx::XciHeader mHdr;
|
nx::XciHeader mHdr;
|
||||||
PfsProcess mRootPfs, mUpdatePfs, mNormalPfs, mSecurePfs;
|
PfsProcess mRootPfs;
|
||||||
|
std::vector<sExtractInfo> mExtractInfo;
|
||||||
|
|
||||||
void displayHeader();
|
void displayHeader();
|
||||||
bool validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash);
|
bool validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash);
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include "CnmtProcess.h"
|
#include "CnmtProcess.h"
|
||||||
#include "NsoProcess.h"
|
#include "NsoProcess.h"
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
UserSettings user_set;
|
UserSettings user_set;
|
||||||
|
@ -29,12 +28,14 @@ int main(int argc, char** argv)
|
||||||
xci.setCliOutputMode(user_set.getCliOutputType());
|
xci.setCliOutputMode(user_set.getCliOutputType());
|
||||||
xci.setVerifyMode(user_set.isVerifyFile());
|
xci.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
if (user_set.getUpdatePath().isSet)
|
if (user_set.getXciUpdatePath().isSet)
|
||||||
xci.setUpdateExtractPath(user_set.getUpdatePath().var);
|
xci.setPartitionForExtract(nx::xci::kUpdatePartitionStr, user_set.getXciUpdatePath().var);
|
||||||
if (user_set.getNormalPath().isSet)
|
if (user_set.getXciNormalPath().isSet)
|
||||||
xci.setNormalExtractPath(user_set.getNormalPath().var);
|
xci.setPartitionForExtract(nx::xci::kNormalPartitionStr, user_set.getXciNormalPath().var);
|
||||||
if (user_set.getSecurePath().isSet)
|
if (user_set.getXciSecurePath().isSet)
|
||||||
xci.setSecureExtractPath(user_set.getSecurePath().var);
|
xci.setPartitionForExtract(nx::xci::kSecurePartitionStr, user_set.getXciSecurePath().var);
|
||||||
|
if (user_set.getXciLogoPath().isSet)
|
||||||
|
xci.setPartitionForExtract(nx::xci::kLogoPartitionStr, user_set.getXciLogoPath().var);
|
||||||
xci.setListFs(user_set.isListFs());
|
xci.setListFs(user_set.isListFs());
|
||||||
|
|
||||||
xci.process();
|
xci.process();
|
||||||
|
@ -77,14 +78,14 @@ int main(int argc, char** argv)
|
||||||
nca.setVerifyMode(user_set.isVerifyFile());
|
nca.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
|
|
||||||
if (user_set.getPart0Path().isSet)
|
if (user_set.getNcaPart0Path().isSet)
|
||||||
nca.setPartition0ExtractPath(user_set.getPart0Path().var);
|
nca.setPartition0ExtractPath(user_set.getNcaPart0Path().var);
|
||||||
if (user_set.getPart1Path().isSet)
|
if (user_set.getNcaPart1Path().isSet)
|
||||||
nca.setPartition1ExtractPath(user_set.getPart1Path().var);
|
nca.setPartition1ExtractPath(user_set.getNcaPart1Path().var);
|
||||||
if (user_set.getPart2Path().isSet)
|
if (user_set.getNcaPart2Path().isSet)
|
||||||
nca.setPartition2ExtractPath(user_set.getPart2Path().var);
|
nca.setPartition2ExtractPath(user_set.getNcaPart2Path().var);
|
||||||
if (user_set.getPart3Path().isSet)
|
if (user_set.getNcaPart3Path().isSet)
|
||||||
nca.setPartition3ExtractPath(user_set.getPart3Path().var);
|
nca.setPartition3ExtractPath(user_set.getNcaPart3Path().var);
|
||||||
nca.setListFs(user_set.isListFs());
|
nca.setListFs(user_set.isListFs());
|
||||||
|
|
||||||
nca.process();
|
nca.process();
|
||||||
|
|
|
@ -35,6 +35,7 @@ struct sOptional
|
||||||
{
|
{
|
||||||
bool isSet;
|
bool isSet;
|
||||||
T var;
|
T var;
|
||||||
|
inline sOptional() : isSet(false) {}
|
||||||
inline const T& operator=(const T& other) { isSet = true; var = other; return var; }
|
inline const T& operator=(const T& other) { isSet = true; var = other; return var; }
|
||||||
inline const sOptional<T>& operator=(const sOptional<T>& other)
|
inline const sOptional<T>& operator=(const sOptional<T>& other)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue