2020-02-26 09:03:43 +00:00
|
|
|
#include "CnmtProcess.h"
|
|
|
|
|
2019-01-31 09:10:19 +00:00
|
|
|
#include <iostream>
|
|
|
|
#include <iomanip>
|
2020-02-26 09:03:43 +00:00
|
|
|
|
2019-01-31 09:10:19 +00:00
|
|
|
#include <fnd/SimpleTextOutput.h>
|
|
|
|
#include <fnd/OffsetAdjustedIFile.h>
|
2020-02-26 09:03:43 +00:00
|
|
|
|
|
|
|
#include <nn/hac/ContentMetaUtil.h>
|
2019-01-31 09:10:19 +00:00
|
|
|
|
|
|
|
CnmtProcess::CnmtProcess() :
|
|
|
|
mFile(),
|
|
|
|
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
|
|
|
mVerify(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CnmtProcess::process()
|
|
|
|
{
|
|
|
|
importCnmt();
|
|
|
|
|
|
|
|
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
|
|
|
displayCnmt();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CnmtProcess::setInputFile(const fnd::SharedPtr<fnd::IFile>& file)
|
|
|
|
{
|
|
|
|
mFile = file;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CnmtProcess::setCliOutputMode(CliOutputMode type)
|
|
|
|
{
|
|
|
|
mCliOutputMode = type;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CnmtProcess::setVerifyMode(bool verify)
|
|
|
|
{
|
|
|
|
mVerify = verify;
|
|
|
|
}
|
|
|
|
|
|
|
|
const nn::hac::ContentMeta& CnmtProcess::getContentMeta() const
|
|
|
|
{
|
|
|
|
return mCnmt;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CnmtProcess::importCnmt()
|
|
|
|
{
|
|
|
|
fnd::Vec<byte_t> scratch;
|
|
|
|
|
|
|
|
if (*mFile == nullptr)
|
|
|
|
{
|
|
|
|
throw fnd::Exception(kModuleName, "No file reader set.");
|
|
|
|
}
|
|
|
|
|
|
|
|
scratch.alloc((*mFile)->size());
|
|
|
|
(*mFile)->read(scratch.data(), 0, scratch.size());
|
|
|
|
|
|
|
|
mCnmt.fromBytes(scratch.data(), scratch.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
void CnmtProcess::displayCnmt()
|
|
|
|
{
|
|
|
|
std::cout << "[ContentMeta]" << std::endl;
|
|
|
|
std::cout << " TitleId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getTitleId() << std::endl;
|
2020-03-19 11:47:48 +00:00
|
|
|
std::cout << " Version: " << nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getTitleVersion()) << " (v" << std::dec << mCnmt.getTitleVersion() << ")"<< std::endl;
|
2020-03-14 14:10:09 +00:00
|
|
|
std::cout << " Type: " << nn::hac::ContentMetaUtil::getContentMetaTypeAsString(mCnmt.getContentMetaType()) << " (" << std::dec << (uint32_t)mCnmt.getContentMetaType() << ")" << std::endl;
|
2020-05-17 04:31:07 +00:00
|
|
|
std::cout << " Attributes: 0x" << std::hex << mCnmt.getAttribute().to_ullong();
|
2020-03-15 05:10:15 +00:00
|
|
|
if (mCnmt.getAttribute().any())
|
2020-02-26 09:03:43 +00:00
|
|
|
{
|
2020-05-17 04:31:07 +00:00
|
|
|
std::vector<std::string> attribute_list;
|
|
|
|
|
2020-03-15 05:10:15 +00:00
|
|
|
for (size_t flag = 0; flag < mCnmt.getAttribute().size(); flag++)
|
2020-02-26 09:03:43 +00:00
|
|
|
{
|
2020-05-17 04:31:07 +00:00
|
|
|
|
2020-03-15 05:10:15 +00:00
|
|
|
if (mCnmt.getAttribute().test(flag))
|
2020-02-26 09:03:43 +00:00
|
|
|
{
|
2020-05-17 04:31:07 +00:00
|
|
|
attribute_list.push_back(nn::hac::ContentMetaUtil::getContentMetaAttributeFlagAsString(nn::hac::cnmt::ContentMetaAttributeFlag(flag)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::cout << " [";
|
|
|
|
for (auto itr = attribute_list.begin(); itr != attribute_list.end(); itr++)
|
|
|
|
{
|
|
|
|
std::cout << *itr;
|
|
|
|
if ((itr + 1) != attribute_list.end())
|
|
|
|
{
|
|
|
|
std::cout << ", ";
|
2020-02-26 09:03:43 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-17 04:31:07 +00:00
|
|
|
std::cout << "]";
|
2020-02-26 09:03:43 +00:00
|
|
|
}
|
2020-05-17 04:31:07 +00:00
|
|
|
std::cout << std::endl;
|
|
|
|
|
2020-03-19 11:47:48 +00:00
|
|
|
std::cout << " StorageId: " << nn::hac::ContentMetaUtil::getStorageIdAsString(mCnmt.getStorageId()) << " (" << std::dec << (uint32_t)mCnmt.getStorageId() << ")" << std::endl;
|
|
|
|
std::cout << " ContentInstallType: " << nn::hac::ContentMetaUtil::getContentInstallTypeAsString(mCnmt.getContentInstallType()) << " (" << std::dec << (uint32_t)mCnmt.getContentInstallType() << ")" << std::endl;
|
|
|
|
std::cout << " RequiredDownloadSystemVersion: " << nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getRequiredDownloadSystemVersion()) << " (v" << mCnmt.getRequiredDownloadSystemVersion() << ")"<< std::endl;
|
2019-01-31 09:10:19 +00:00
|
|
|
switch(mCnmt.getContentMetaType())
|
|
|
|
{
|
2020-03-14 14:10:09 +00:00
|
|
|
case (nn::hac::cnmt::ContentMetaType::Application):
|
2019-01-31 09:10:19 +00:00
|
|
|
std::cout << " ApplicationExtendedHeader:" << std::endl;
|
2020-03-19 11:47:48 +00:00
|
|
|
std::cout << " RequiredApplicationVersion: " << nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getApplicationMetaExtendedHeader().getRequiredApplicationVersion()) << " (v" << std::dec << mCnmt.getApplicationMetaExtendedHeader().getRequiredApplicationVersion() << ")"<< std::endl;
|
|
|
|
std::cout << " RequiredSystemVersion: " << nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion()) << " (v" << std::dec << mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion() << ")"<< std::endl;
|
2020-03-15 05:10:15 +00:00
|
|
|
std::cout << " PatchId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getApplicationMetaExtendedHeader().getPatchId() << std::endl;
|
2019-01-31 09:10:19 +00:00
|
|
|
break;
|
2020-03-14 14:10:09 +00:00
|
|
|
case (nn::hac::cnmt::ContentMetaType::Patch):
|
2019-01-31 09:10:19 +00:00
|
|
|
std::cout << " PatchMetaExtendedHeader:" << std::endl;
|
2020-03-19 11:47:48 +00:00
|
|
|
std::cout << " RequiredSystemVersion: " << nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion()) << " (v" << std::dec << mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion() << ")"<< std::endl;
|
2019-01-31 09:10:19 +00:00
|
|
|
std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getPatchMetaExtendedHeader().getApplicationId() << std::endl;
|
|
|
|
break;
|
2020-03-14 14:10:09 +00:00
|
|
|
case (nn::hac::cnmt::ContentMetaType::AddOnContent):
|
2019-01-31 09:10:19 +00:00
|
|
|
std::cout << " AddOnContentMetaExtendedHeader:" << std::endl;
|
2020-03-19 11:47:48 +00:00
|
|
|
std::cout << " RequiredApplicationVersion: " << nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion()) << " (v" << std::dec << mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion() << ")" << std::endl;
|
2019-01-31 09:10:19 +00:00
|
|
|
std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getAddOnContentMetaExtendedHeader().getApplicationId() << std::endl;
|
|
|
|
break;
|
2020-03-14 14:10:09 +00:00
|
|
|
case (nn::hac::cnmt::ContentMetaType::Delta):
|
2019-01-31 09:10:19 +00:00
|
|
|
std::cout << " DeltaMetaExtendedHeader:" << std::endl;
|
|
|
|
std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getDeltaMetaExtendedHeader().getApplicationId() << std::endl;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (mCnmt.getContentInfo().size() > 0)
|
|
|
|
{
|
|
|
|
printf(" ContentInfo:\n");
|
|
|
|
for (size_t i = 0; i < mCnmt.getContentInfo().size(); i++)
|
|
|
|
{
|
|
|
|
const nn::hac::ContentInfo& info = mCnmt.getContentInfo()[i];
|
|
|
|
std::cout << " " << std::dec << i << std::endl;
|
2020-03-14 14:10:09 +00:00
|
|
|
std::cout << " Type: " << nn::hac::ContentMetaUtil::getContentTypeAsString(info.getContentType()) << " (" << std::dec << (uint32_t)info.getContentType() << ")" << std::endl;
|
2020-05-17 04:31:07 +00:00
|
|
|
std::cout << " Id: " << fnd::SimpleTextOutput::arrayToString(info.getContentId().data(), info.getContentId().size(), false, "") << std::endl;
|
2019-01-31 09:10:19 +00:00
|
|
|
std::cout << " Size: 0x" << std::hex << info.getContentSize() << std::endl;
|
|
|
|
std::cout << " Hash: " << fnd::SimpleTextOutput::arrayToString(info.getContentHash().bytes, sizeof(info.getContentHash()), false, "") << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mCnmt.getContentMetaInfo().size() > 0)
|
|
|
|
{
|
|
|
|
std::cout << " ContentMetaInfo:" << std::endl;
|
2020-05-23 15:49:56 +00:00
|
|
|
displayContentMetaInfoList(mCnmt.getContentMetaInfo(), " ");
|
|
|
|
}
|
|
|
|
|
|
|
|
// print extended data
|
|
|
|
if (mCnmt.getContentMetaType() == nn::hac::cnmt::ContentMetaType::Patch && mCnmt.getPatchMetaExtendedHeader().getExtendedDataSize() != 0)
|
|
|
|
{
|
|
|
|
// this is stubbed as the raw output is for development purposes
|
|
|
|
//std::cout << " PatchMetaExtendedData:" << std::endl;
|
|
|
|
//fnd::SimpleTextOutput::hxdStyleDump(mCnmt.getPatchMetaExtendedData().data(), mCnmt.getPatchMetaExtendedData().size());
|
|
|
|
}
|
|
|
|
else if (mCnmt.getContentMetaType() == nn::hac::cnmt::ContentMetaType::Delta && mCnmt.getDeltaMetaExtendedHeader().getExtendedDataSize() != 0)
|
|
|
|
{
|
|
|
|
// this is stubbed as the raw output is for development purposes
|
|
|
|
//std::cout << " DeltaMetaExtendedData:" << std::endl;
|
|
|
|
//fnd::SimpleTextOutput::hxdStyleDump(mCnmt.getDeltaMetaExtendedData().data(), mCnmt.getDeltaMetaExtendedData().size());
|
|
|
|
}
|
|
|
|
else if (mCnmt.getContentMetaType() == nn::hac::cnmt::ContentMetaType::SystemUpdate && mCnmt.getSystemUpdateMetaExtendedHeader().getExtendedDataSize() != 0)
|
|
|
|
{
|
|
|
|
std::cout << " SystemUpdateMetaExtendedData:" << std::endl;
|
|
|
|
std::cout << " FormatVersion: " << std::dec << mCnmt.getSystemUpdateMetaExtendedData().getFormatVersion() << std::endl;
|
|
|
|
std::cout << " FirmwareVariation:" << std::endl;
|
|
|
|
auto variation_info = mCnmt.getSystemUpdateMetaExtendedData().getFirmwareVariationInfo();
|
|
|
|
for (size_t i = 0; i < mCnmt.getSystemUpdateMetaExtendedData().getFirmwareVariationInfo().size(); i++)
|
2019-01-31 09:10:19 +00:00
|
|
|
{
|
2020-05-23 15:49:56 +00:00
|
|
|
std::cout << " " << std::dec << i << std::endl;
|
|
|
|
std::cout << " FirmwareVariationId: 0x" << std::hex << variation_info[i].variation_id << std::endl;
|
|
|
|
if (mCnmt.getSystemUpdateMetaExtendedData().getFormatVersion() == 2)
|
2020-02-26 09:03:43 +00:00
|
|
|
{
|
2020-05-23 15:49:56 +00:00
|
|
|
std::cout << " ReferToBase: " << std::boolalpha << variation_info[i].meta.empty() << std::endl;
|
|
|
|
if (variation_info[i].meta.empty() == false)
|
2020-02-26 09:03:43 +00:00
|
|
|
{
|
2020-05-23 15:49:56 +00:00
|
|
|
std::cout << " ContentMeta:" << std::endl;
|
|
|
|
displayContentMetaInfoList(variation_info[i].meta, " ");
|
2020-02-26 09:03:43 +00:00
|
|
|
}
|
2020-05-23 15:49:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-05-17 04:31:07 +00:00
|
|
|
|
2020-05-23 15:49:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
std::cout << " Digest: " << fnd::SimpleTextOutput::arrayToString(mCnmt.getDigest().data(), mCnmt.getDigest().size(), false, "") << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CnmtProcess::displayContentMetaInfo(const nn::hac::ContentMetaInfo& content_meta_info, const std::string& prefix)
|
|
|
|
{
|
|
|
|
std::cout << prefix << "Id: 0x" << std::hex << std::setw(16) << std::setfill('0') << content_meta_info.getTitleId() << std::endl;
|
|
|
|
std::cout << prefix << "Version: " << nn::hac::ContentMetaUtil::getVersionAsString(content_meta_info.getTitleVersion()) << " (v" << std::dec << content_meta_info.getTitleVersion() << ")"<< std::endl;
|
|
|
|
std::cout << prefix << "Type: " << nn::hac::ContentMetaUtil::getContentMetaTypeAsString(content_meta_info.getContentMetaType()) << " (" << std::dec << (uint32_t)content_meta_info.getContentMetaType() << ")" << std::endl;
|
|
|
|
std::cout << prefix << "Attributes: 0x" << std::hex << content_meta_info.getAttribute().to_ullong();
|
|
|
|
if (content_meta_info.getAttribute().any())
|
|
|
|
{
|
|
|
|
std::vector<std::string> attribute_list;
|
|
|
|
|
|
|
|
for (size_t flag = 0; flag < content_meta_info.getAttribute().size(); flag++)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (content_meta_info.getAttribute().test(flag))
|
|
|
|
{
|
|
|
|
attribute_list.push_back(nn::hac::ContentMetaUtil::getContentMetaAttributeFlagAsString(nn::hac::cnmt::ContentMetaAttributeFlag(flag)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::cout << " [";
|
|
|
|
for (auto itr = attribute_list.begin(); itr != attribute_list.end(); itr++)
|
|
|
|
{
|
|
|
|
std::cout << *itr;
|
|
|
|
if ((itr + 1) != attribute_list.end())
|
|
|
|
{
|
|
|
|
std::cout << ", ";
|
2020-02-26 09:03:43 +00:00
|
|
|
}
|
2019-01-31 09:10:19 +00:00
|
|
|
}
|
2020-05-23 15:49:56 +00:00
|
|
|
std::cout << "]";
|
2019-01-31 09:10:19 +00:00
|
|
|
}
|
2020-05-23 15:49:56 +00:00
|
|
|
}
|
2019-01-31 09:10:19 +00:00
|
|
|
|
2020-05-23 15:49:56 +00:00
|
|
|
void CnmtProcess::displayContentMetaInfoList(const std::vector<nn::hac::ContentMetaInfo>& content_meta_info_list, const std::string& prefix)
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < content_meta_info_list.size(); i++)
|
|
|
|
{
|
|
|
|
const nn::hac::ContentMetaInfo& info = mCnmt.getContentMetaInfo()[i];
|
|
|
|
std::cout << prefix << std::dec << i << std::endl;
|
|
|
|
displayContentMetaInfo(info, prefix + " ");
|
|
|
|
std::cout << std::endl;
|
|
|
|
}
|
2020-02-26 09:03:43 +00:00
|
|
|
}
|