[nx|nstool] Added support for xci logo partition.

This commit is contained in:
jakcron 2018-06-03 15:10:47 +08:00
parent 7ace472d77
commit a8f39b721d
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 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
{

View file

@ -3,6 +3,7 @@
#include <string>
#include <fnd/types.h>
#include <fnd/IFile.h>
#include <nx/npdm.h>
#include <nx/NsoHeader.h>
#include "nstool.h"

View file

@ -48,6 +48,7 @@ void UserSettings::showHelp()
printf(" --listfs Print file system in embedded partitions\n");
printf(" --update Extract \"update\" 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("\n PFS0/HFS0 (PartitionFs), RomFs, NSP (Ninendo Submission Package)\n");
printf(" nstool [--listfs] [--fsdir <dir>] <file>\n");
@ -103,19 +104,24 @@ const sOptional<nx::npdm::InstructionType>& UserSettings::getArchType() const
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
@ -123,24 +129,24 @@ const sOptional<std::string>& UserSettings::getFsPath() const
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.");
}
cmd_args.clear();
cmd_args.input_path = args.back();
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];
}
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")
{
if (!hasParamter) throw fnd::Exception(kModuleName, args[i] + " requries a parameter.");
@ -530,20 +541,20 @@ void UserSettings::populateUserSettings(sCmdArgs& args)
mInputPath = *args.input_path;
mVerifyFile = args.verify_file.isSet;
mListFs = args.list_fs.isSet;
mUpdatePath = args.update_path;
mNormalPath = args.normal_path;
mSecurePath = args.secure_path;
mXciUpdatePath = args.update_path;
mXciNormalPath = args.normal_path;
mXciSecurePath = args.secure_path;
mXciLogoPath = args.logo_path;
mFsPath = args.fs_path;
mPart0Path = args.part0_path;
mPart1Path = args.part1_path;
mPart2Path = args.part2_path;
mPart3Path = args.part3_path;
mNcaPart0Path = args.part0_path;
mNcaPart1Path = args.part1_path;
mNcaPart2Path = args.part2_path;
mNcaPart3Path = args.part3_path;
// determine the architecture type for NSO
if (args.arch_type.isSet)
mArchType = getInstructionTypeFromString(*args.arch_type);
else
mArchType.isSet = false;
// determine output path
if (args.verbose_output.isSet)

View file

@ -24,20 +24,22 @@ public:
const sOptional<nx::npdm::InstructionType>& getArchType() const;
// specialised paths
const sOptional<std::string>& getUpdatePath() const;
const sOptional<std::string>& getNormalPath() const;
const sOptional<std::string>& getSecurePath() const;
const sOptional<std::string>& getXciUpdatePath() const;
const sOptional<std::string>& getXciNormalPath() const;
const sOptional<std::string>& getXciSecurePath() const;
const sOptional<std::string>& getXciLogoPath() const;
const sOptional<std::string>& getFsPath() const;
const sOptional<std::string>& getPart0Path() const;
const sOptional<std::string>& getPart1Path() const;
const sOptional<std::string>& getPart2Path() const;
const sOptional<std::string>& getPart3Path() const;
const sOptional<std::string>& getNcaPart0Path() const;
const sOptional<std::string>& getNcaPart1Path() const;
const sOptional<std::string>& getNcaPart2Path() const;
const sOptional<std::string>& getNcaPart3Path() const;
private:
const std::string kModuleName = "UserSettings";
struct sCmdArgs
{
sCmdArgs() {}
sOptional<std::string> input_path;
sOptional<bool> devkit_keys;
sOptional<std::string> keyset_path;
@ -49,6 +51,7 @@ private:
sOptional<std::string> update_path;
sOptional<std::string> normal_path;
sOptional<std::string> secure_path;
sOptional<std::string> logo_path;
sOptional<std::string> fs_path;
sOptional<std::string> nca_titlekey;
sOptional<std::string> nca_bodykey;
@ -57,29 +60,6 @@ private:
sOptional<std::string> part2_path;
sOptional<std::string> part3_path;
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;
@ -89,15 +69,16 @@ private:
CliOutputType mOutputType;
bool mListFs;
sOptional<std::string> mUpdatePath;
sOptional<std::string> mNormalPath;
sOptional<std::string> mSecurePath;
sOptional<std::string> mXciUpdatePath;
sOptional<std::string> mXciNormalPath;
sOptional<std::string> mXciSecurePath;
sOptional<std::string> mXciLogoPath;
sOptional<std::string> mFsPath;
sOptional<std::string> mPart0Path;
sOptional<std::string> mPart1Path;
sOptional<std::string> mPart2Path;
sOptional<std::string> mPart3Path;
sOptional<std::string> mNcaPart0Path;
sOptional<std::string> mNcaPart1Path;
sOptional<std::string> mNcaPart2Path;
sOptional<std::string> mNcaPart3Path;
sOptional<nx::npdm::InstructionType> mArchType;

View file

@ -163,12 +163,13 @@ void XciProcess::processPartitionPfs()
tmp.setVerifyMode(mVerify);
tmp.setCliOutputMode(mCliOutputType);
tmp.setMountPointName(kXciMountPointName + rootPartitions[i].name);
if (mUpdatePath.doExtract && rootPartitions[i].name == "update")
tmp.setExtractPath(mUpdatePath.path);
if (mNormalPath.doExtract && rootPartitions[i].name == "normal")
tmp.setExtractPath(mNormalPath.path);
if (mSecurePath.doExtract && rootPartitions[i].name == "secure")
tmp.setExtractPath(mSecurePath.path);
for (size_t j = 0; j < mExtractInfo.size(); j++)
{
if (mExtractInfo[j].partition_name == rootPartitions[i].name)
{
tmp.setExtractPath(mExtractInfo[j].extract_path);
}
}
tmp.process();
}
}
@ -180,13 +181,8 @@ XciProcess::XciProcess() :
mVerify(false),
mListFs(false),
mRootPfs(),
mUpdatePfs(),
mNormalPfs(),
mSecurePfs()
mExtractInfo()
{
mUpdatePath.doExtract = false;
mNormalPath.doExtract = false;
mSecurePath.doExtract = false;
}
XciProcess::~XciProcess()
@ -255,22 +251,9 @@ void XciProcess::setVerifyMode(bool 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;
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;
mExtractInfo.push_back({partition_name, extract_path});
}
void XciProcess::setListFs(bool list_fs)

View file

@ -24,9 +24,7 @@ public:
void setVerifyMode(bool verify);
// xci specific
void setUpdateExtractPath(const std::string& path);
void setNormalExtractPath(const std::string& path);
void setSecureExtractPath(const std::string& path);
void setPartitionForExtract(const std::string& partition_name, const std::string& extract_path);
void setListFs(bool list_fs);
private:
@ -39,17 +37,18 @@ private:
CliOutputType mCliOutputType;
bool mVerify;
struct sExtract
struct sExtractInfo
{
std::string path;
bool doExtract;
} mUpdatePath, mNormalPath, mSecurePath;
std::string partition_name;
std::string extract_path;
};
bool mListFs;
nx::sXciHeaderPage mHdrPage;
nx::XciHeader mHdr;
PfsProcess mRootPfs, mUpdatePfs, mNormalPfs, mSecurePfs;
PfsProcess mRootPfs;
std::vector<sExtractInfo> mExtractInfo;
void displayHeader();
bool validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash);

View file

@ -9,7 +9,6 @@
#include "CnmtProcess.h"
#include "NsoProcess.h"
int main(int argc, char** argv)
{
UserSettings user_set;
@ -29,12 +28,14 @@ int main(int argc, char** argv)
xci.setCliOutputMode(user_set.getCliOutputType());
xci.setVerifyMode(user_set.isVerifyFile());
if (user_set.getUpdatePath().isSet)
xci.setUpdateExtractPath(user_set.getUpdatePath().var);
if (user_set.getNormalPath().isSet)
xci.setNormalExtractPath(user_set.getNormalPath().var);
if (user_set.getSecurePath().isSet)
xci.setSecureExtractPath(user_set.getSecurePath().var);
if (user_set.getXciUpdatePath().isSet)
xci.setPartitionForExtract(nx::xci::kUpdatePartitionStr, user_set.getXciUpdatePath().var);
if (user_set.getXciNormalPath().isSet)
xci.setPartitionForExtract(nx::xci::kNormalPartitionStr, user_set.getXciNormalPath().var);
if (user_set.getXciSecurePath().isSet)
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.process();
@ -77,14 +78,14 @@ int main(int argc, char** argv)
nca.setVerifyMode(user_set.isVerifyFile());
if (user_set.getPart0Path().isSet)
nca.setPartition0ExtractPath(user_set.getPart0Path().var);
if (user_set.getPart1Path().isSet)
nca.setPartition1ExtractPath(user_set.getPart1Path().var);
if (user_set.getPart2Path().isSet)
nca.setPartition2ExtractPath(user_set.getPart2Path().var);
if (user_set.getPart3Path().isSet)
nca.setPartition3ExtractPath(user_set.getPart3Path().var);
if (user_set.getNcaPart0Path().isSet)
nca.setPartition0ExtractPath(user_set.getNcaPart0Path().var);
if (user_set.getNcaPart1Path().isSet)
nca.setPartition1ExtractPath(user_set.getNcaPart1Path().var);
if (user_set.getNcaPart2Path().isSet)
nca.setPartition2ExtractPath(user_set.getNcaPart2Path().var);
if (user_set.getNcaPart3Path().isSet)
nca.setPartition3ExtractPath(user_set.getNcaPart3Path().var);
nca.setListFs(user_set.isListFs());
nca.process();

View file

@ -35,6 +35,7 @@ struct sOptional
{
bool isSet;
T var;
inline sOptional() : isSet(false) {}
inline const T& operator=(const T& other) { isSet = true; var = other; return var; }
inline const sOptional<T>& operator=(const sOptional<T>& other)
{