Merge pull request #14 from jakcron/xci-development

[nx|nstool] Added support for xci logo partition.
This commit is contained in:
Jack 2018-06-03 15:11:48 +08:00 committed by GitHub
commit f13b4ec2a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 93 additions and 111 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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