Port MetaProcess to libtoolchain.

This commit is contained in:
jakcron 2021-10-11 22:12:23 +08:00
parent 1444dff37a
commit 672828839a
5 changed files with 133 additions and 130 deletions

View file

@ -187,6 +187,7 @@
<ClCompile Include="..\..\..\src\GameCardProcess.cpp" /> <ClCompile Include="..\..\..\src\GameCardProcess.cpp" />
<ClCompile Include="..\..\..\src\KeyBag.cpp" /> <ClCompile Include="..\..\..\src\KeyBag.cpp" />
<ClCompile Include="..\..\..\src\main.cpp" /> <ClCompile Include="..\..\..\src\main.cpp" />
<ClCompile Include="..\..\..\src\MetaProcess.cpp" />
<ClCompile Include="..\..\..\src\NacpProcess.cpp" /> <ClCompile Include="..\..\..\src\NacpProcess.cpp" />
<ClCompile Include="..\..\..\src\NroProcess.cpp" /> <ClCompile Include="..\..\..\src\NroProcess.cpp" />
<ClCompile Include="..\..\..\src\NsoProcess.cpp" /> <ClCompile Include="..\..\..\src\NsoProcess.cpp" />

View file

@ -149,5 +149,8 @@
<ClCompile Include="..\..\..\src\NroProcess.cpp"> <ClCompile Include="..\..\..\src\NroProcess.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\..\src\MetaProcess.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -1,16 +1,12 @@
#include "MetaProcess.h" #include "MetaProcess.h"
#include <iostream>
#include <iomanip>
#include <nn/hac/AccessControlInfoUtil.h> #include <nn/hac/AccessControlInfoUtil.h>
#include <nn/hac/FileSystemAccessUtil.h> #include <nn/hac/FileSystemAccessUtil.h>
#include <nn/hac/KernelCapabilityUtil.h> #include <nn/hac/KernelCapabilityUtil.h>
#include <nn/hac/MetaUtil.h> #include <nn/hac/MetaUtil.h>
#include <fnd/SimpleTextOutput.h>
nstool::MetaProcess::MetaProcess() : nstool::MetaProcess::MetaProcess() :
mModuleName("nstool::MetaProcess"),
mFile(), mFile(),
mCliOutputMode(true, false, false, false), mCliOutputMode(true, false, false, false),
mVerify(false) mVerify(false)
@ -76,15 +72,26 @@ const nn::hac::Meta& nstool::MetaProcess::getMeta() const
void nstool::MetaProcess::importMeta() void nstool::MetaProcess::importMeta()
{ {
tc::ByteData scratch; if (mFile == nullptr)
if (*mFile == nullptr)
{ {
throw tc::Exception(kModuleName, "No file reader set."); throw tc::Exception(mModuleName, "No file reader set.");
}
if (mFile->canRead() == false || mFile->canSeek() == false)
{
throw tc::NotSupportedException(mModuleName, "Input stream requires read/seek permissions.");
} }
scratch.alloc((*mFile)->size()); // check if file_size is greater than 20MB, don't import.
(*mFile)->read(scratch.data(), 0, scratch.size()); size_t file_size = tc::io::IOUtil::castInt64ToSize(mFile->length());
if (file_size > (0x100000 * 20))
{
throw tc::Exception(mModuleName, "File too large.");
}
// read meta
tc::ByteData scratch = tc::ByteData(file_size);
mFile->seek(0, tc::io::SeekOrigin::Begin);
mFile->read(scratch.data(), scratch.size());
mMeta.fromBytes(scratch.data(), scratch.size()); mMeta.fromBytes(scratch.data(), scratch.size());
} }
@ -92,14 +99,15 @@ void nstool::MetaProcess::importMeta()
void nstool::MetaProcess::validateAcidSignature(const nn::hac::AccessControlInfoDesc& acid, byte_t key_generation) void nstool::MetaProcess::validateAcidSignature(const nn::hac::AccessControlInfoDesc& acid, byte_t key_generation)
{ {
try { try {
fnd::rsa::sRsa2048Key acid_sign_key; if (mKeyCfg.acid_sign_key.find(key_generation) == mKeyCfg.acid_sign_key.end())
if (mKeyCfg.getAcidSignKey(acid_sign_key, key_generation) != true) {
throw tc::Exception(); throw tc::Exception("Failed to load rsa public key");
}
acid.validateSignature(acid_sign_key); acid.validateSignature(mKeyCfg.acid_sign_key.at(key_generation));
} }
catch (...) { catch (tc::Exception& e) {
std::cout << "[WARNING] ACID Signature: FAIL" << std::endl; fmt::print("[WARNING] ACID Signature: FAIL ({:s})\n", e.error());
} }
} }
@ -109,20 +117,27 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
// check Program ID // check Program ID
if (acid.getProgramIdRestrict().min > 0 && aci.getProgramId() < acid.getProgramIdRestrict().min) if (acid.getProgramIdRestrict().min > 0 && aci.getProgramId() < acid.getProgramIdRestrict().min)
{ {
std::cout << "[WARNING] ACI ProgramId: FAIL (Outside Legal Range)" << std::endl; fmt::print("[WARNING] ACI ProgramId: FAIL (Outside Legal Range)\n");
} }
else if (acid.getProgramIdRestrict().max > 0 && aci.getProgramId() > acid.getProgramIdRestrict().max) else if (acid.getProgramIdRestrict().max > 0 && aci.getProgramId() > acid.getProgramIdRestrict().max)
{ {
std::cout << "[WARNING] ACI ProgramId: FAIL (Outside Legal Range)" << std::endl; fmt::print("[WARNING] ACI ProgramId: FAIL (Outside Legal Range)\n");
} }
auto fs_access = aci.getFileSystemAccessControl().getFsAccess(); auto fs_access = aci.getFileSystemAccessControl().getFsAccess();
auto desc_fs_access = acid.getFileSystemAccessControl().getFsAccess(); auto desc_fs_access = acid.getFileSystemAccessControl().getFsAccess();
for (size_t i = 0; i < fs_access.size(); i++) for (size_t i = 0; i < fs_access.size(); i++)
{ {
if (fs_access.test(i) && desc_fs_access.test(i) == false) bool rightFound = false;
for (size_t j = 0; j < desc_fs_access.size() && rightFound == false; j++)
{ {
std::cout << "[WARNING] ACI/FAC FsaRights: FAIL (" << nn::hac::FileSystemAccessUtil::getFsAccessFlagAsString(nn::hac::fac::FsAccessFlag(i)) << " not permitted)" << std::endl; if (fs_access[i] == desc_fs_access[j])
rightFound = true;
}
if (rightFound == false)
{
fmt::print("[WARNING] ACI/FAC FsaRights: FAIL ({:s} not permitted)\n", nn::hac::FileSystemAccessUtil::getFsAccessFlagAsString(fs_access[i]));
} }
} }
@ -138,7 +153,7 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
if (rightFound == false) if (rightFound == false)
{ {
std::cout << "[WARNING] ACI/FAC ContentOwnerId: FAIL (" << std::hex << std::setw(16) << std::setfill('0') << aci.getFileSystemAccessControl().getContentOwnerIdList()[i] << " not permitted)" << std::endl; fmt::print("[WARNING] ACI/FAC ContentOwnerId: FAIL (0x{:016x} not permitted)\n", aci.getFileSystemAccessControl().getContentOwnerIdList()[i]);
} }
} }
@ -154,7 +169,7 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
if (rightFound == false) if (rightFound == false)
{ {
std::cout << "[WARNING] ACI/FAC SaveDataOwnerId: FAIL (" << std::hex << std::setw(16) << std::setfill('0') << aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].id << "(" << std::dec << (uint32_t)aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].access_type << ") not permitted)" << std::endl; fmt::print("[WARNING] ACI/FAC SaveDataOwnerId: FAIL (0x{:016x} ({:d}) not permitted)\n", aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].id, aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].access_type);
} }
} }
@ -170,7 +185,7 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
if (rightFound == false) if (rightFound == false)
{ {
std::cout << "[WARNING] ACI/SAC ServiceList: FAIL (" << aci.getServiceAccessControl().getServiceList()[i].getName() << (aci.getServiceAccessControl().getServiceList()[i].isServer()? " (Server)" : "") << " not permitted)" << std::endl; fmt::print("[WARNING] ACI/SAC ServiceList: FAIL ({:s}{:s} not permitted)\n", aci.getServiceAccessControl().getServiceList()[i].getName(), (aci.getServiceAccessControl().getServiceList()[i].isServer()? " (Server)" : ""));
} }
} }
@ -178,19 +193,19 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
// check thread info // check thread info
if (aci.getKernelCapabilities().getThreadInfo().getMaxCpuId() != acid.getKernelCapabilities().getThreadInfo().getMaxCpuId()) if (aci.getKernelCapabilities().getThreadInfo().getMaxCpuId() != acid.getKernelCapabilities().getThreadInfo().getMaxCpuId())
{ {
std::cout << "[WARNING] ACI/KC ThreadInfo/MaxCpuId: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getThreadInfo().getMaxCpuId() << " not permitted)" << std::endl; fmt::print("[WARNING] ACI/KC ThreadInfo/MaxCpuId: FAIL ({:d} not permitted)\n", aci.getKernelCapabilities().getThreadInfo().getMaxCpuId());
} }
if (aci.getKernelCapabilities().getThreadInfo().getMinCpuId() != acid.getKernelCapabilities().getThreadInfo().getMinCpuId()) if (aci.getKernelCapabilities().getThreadInfo().getMinCpuId() != acid.getKernelCapabilities().getThreadInfo().getMinCpuId())
{ {
std::cout << "[WARNING] ACI/KC ThreadInfo/MinCpuId: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getThreadInfo().getMinCpuId() << " not permitted)" << std::endl; fmt::print("[WARNING] ACI/KC ThreadInfo/MinCpuId: FAIL ({:d} not permitted)\n", aci.getKernelCapabilities().getThreadInfo().getMinCpuId());
} }
if (aci.getKernelCapabilities().getThreadInfo().getMaxPriority() != acid.getKernelCapabilities().getThreadInfo().getMaxPriority()) if (aci.getKernelCapabilities().getThreadInfo().getMaxPriority() != acid.getKernelCapabilities().getThreadInfo().getMaxPriority())
{ {
std::cout << "[WARNING] ACI/KC ThreadInfo/MaxPriority: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getThreadInfo().getMaxPriority() << " not permitted)" << std::endl; fmt::print("[WARNING] ACI/KC ThreadInfo/MaxPriority: FAIL ({:d} not permitted)\n", aci.getKernelCapabilities().getThreadInfo().getMaxPriority());
} }
if (aci.getKernelCapabilities().getThreadInfo().getMinPriority() != acid.getKernelCapabilities().getThreadInfo().getMinPriority()) if (aci.getKernelCapabilities().getThreadInfo().getMinPriority() != acid.getKernelCapabilities().getThreadInfo().getMinPriority())
{ {
std::cout << "[WARNING] ACI/KC ThreadInfo/MinPriority: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getThreadInfo().getMinPriority() << " not permitted)" << std::endl; fmt::print("[WARNING] ACI/KC ThreadInfo/MinPriority: FAIL ({:d} not permitted)\n", aci.getKernelCapabilities().getThreadInfo().getMinPriority());
} }
// check system calls // check system calls
auto syscall_ids = aci.getKernelCapabilities().getSystemCalls().getSystemCallIds(); auto syscall_ids = aci.getKernelCapabilities().getSystemCalls().getSystemCallIds();
@ -199,7 +214,7 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
{ {
if (syscall_ids.test(i) && desc_syscall_ids.test(i) == false) if (syscall_ids.test(i) && desc_syscall_ids.test(i) == false)
{ {
std::cout << "[WARNING] ACI/KC SystemCallList: FAIL (" << nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(i)) << " not permitted)" << std::endl; fmt::print("[WARNING] ACI/KC SystemCallList: FAIL ({:s} not permitted)\n", nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(i)));
} }
} }
// check memory maps // check memory maps
@ -216,7 +231,7 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
{ {
auto map = aci.getKernelCapabilities().getMemoryMaps().getMemoryMaps()[i]; auto map = aci.getKernelCapabilities().getMemoryMaps().getMemoryMaps()[i];
std::cout << "[WARNING] ACI/KC MemoryMap: FAIL (0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)map.addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(map.addr + map.size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemoryPermissionAsString(map.perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMappingTypeAsString(map.type) << ") not permitted)" << std::endl; fmt::print("[WARNING] ACI/KC MemoryMap: FAIL ({:s} not permitted)\n", formatMappingAsString(map));
} }
} }
for (size_t i = 0; i < aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps().size(); i++) for (size_t i = 0; i < aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps().size(); i++)
@ -232,7 +247,7 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
{ {
auto map = aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps()[i]; auto map = aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps()[i];
std::cout << "[WARNING] ACI/KC IoMemoryMap: FAIL (0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)map.addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(map.addr + map.size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemoryPermissionAsString(map.perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMappingTypeAsString(map.type) << ") not permitted)" << std::endl; fmt::print("[WARNING] ACI/KC IoMemoryMap: FAIL ({:s} not permitted)\n", formatMappingAsString(map));
} }
} }
// check interupts // check interupts
@ -247,25 +262,25 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
if (rightFound == false) if (rightFound == false)
{ {
std::cout << "[WARNING] ACI/KC InteruptsList: FAIL (0x" << std::hex << (uint32_t)aci.getKernelCapabilities().getInterupts().getInteruptList()[i] << " not permitted)" << std::endl; fmt::print("[WARNING] ACI/KC InteruptsList: FAIL (0x{:x} not permitted)\n", aci.getKernelCapabilities().getInterupts().getInteruptList()[i]);
} }
} }
// check misc params // check misc params
if (aci.getKernelCapabilities().getMiscParams().getProgramType() != acid.getKernelCapabilities().getMiscParams().getProgramType()) if (aci.getKernelCapabilities().getMiscParams().getProgramType() != acid.getKernelCapabilities().getMiscParams().getProgramType())
{ {
std::cout << "[WARNING] ACI/KC ProgramType: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getMiscParams().getProgramType() << " not permitted)" << std::endl; fmt::print("[WARNING] ACI/KC ProgramType: FAIL ({:d} not permitted)\n", aci.getKernelCapabilities().getMiscParams().getProgramType());
} }
// check kernel version // check kernel version
uint32_t aciKernelVersion = (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMajor() << 16 | (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMinor(); uint32_t aciKernelVersion = (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMajor() << 16 | (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMinor();
uint32_t acidKernelVersion = (uint32_t)acid.getKernelCapabilities().getKernelVersion().getVerMajor() << 16 | (uint32_t)acid.getKernelCapabilities().getKernelVersion().getVerMinor(); uint32_t acidKernelVersion = (uint32_t)acid.getKernelCapabilities().getKernelVersion().getVerMajor() << 16 | (uint32_t)acid.getKernelCapabilities().getKernelVersion().getVerMinor();
if (aciKernelVersion < acidKernelVersion) if (aciKernelVersion < acidKernelVersion)
{ {
std::cout << "[WARNING] ACI/KC RequiredKernelVersion: FAIL (" << std::dec << aci.getKernelCapabilities().getKernelVersion().getVerMajor() << "." << aci.getKernelCapabilities().getKernelVersion().getVerMinor() << " not permitted)" << std::endl; fmt::print("[WARNING] ACI/KC RequiredKernelVersion: FAIL ({:d}.{:d} not permitted)\n", aci.getKernelCapabilities().getKernelVersion().getVerMajor(), aci.getKernelCapabilities().getKernelVersion().getVerMinor());
} }
// check handle table size // check handle table size
if (aci.getKernelCapabilities().getHandleTableSize().getHandleTableSize() > acid.getKernelCapabilities().getHandleTableSize().getHandleTableSize()) if (aci.getKernelCapabilities().getHandleTableSize().getHandleTableSize() > acid.getKernelCapabilities().getHandleTableSize().getHandleTableSize())
{ {
std::cout << "[WARNING] ACI/KC HandleTableSize: FAIL (0x" << std::hex << (uint32_t)aci.getKernelCapabilities().getHandleTableSize().getHandleTableSize() << " too large)" << std::endl; fmt::print("[WARNING] ACI/KC HandleTableSize: FAIL (0x{:x} too large)\n", aci.getKernelCapabilities().getHandleTableSize().getHandleTableSize());
} }
// check misc flags // check misc flags
auto misc_flags = aci.getKernelCapabilities().getMiscFlags().getMiscFlags(); auto misc_flags = aci.getKernelCapabilities().getMiscFlags().getMiscFlags();
@ -274,205 +289,187 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
{ {
if (misc_flags.test(i) && desc_misc_flags.test(i) == false) if (misc_flags.test(i) && desc_misc_flags.test(i) == false)
{ {
std::cout << "[WARNING] ACI/KC MiscFlag: FAIL (" << nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(i)) << " not permitted)" << std::endl; fmt::print("[WARNING] ACI/KC MiscFlag: FAIL ({:s} not permitted)\n", nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(i)));
} }
} }
} }
void nstool::MetaProcess::displayMetaHeader(const nn::hac::Meta& hdr) void nstool::MetaProcess::displayMetaHeader(const nn::hac::Meta& hdr)
{ {
std::cout << "[Meta Header]" << std::endl; fmt::print("[Meta Header]\n");
std::cout << " ACID KeyGeneration: " << std::dec << (uint32_t)hdr.getAccessControlInfoDescKeyGeneration() << std::endl; fmt::print(" ACID KeyGeneration: {:d}\n", hdr.getAccessControlInfoDescKeyGeneration());
std::cout << " Flags:" << std::endl; fmt::print(" Flags:\n");
std::cout << " Is64BitInstruction: " << std::boolalpha << hdr.getIs64BitInstructionFlag() << std::endl; fmt::print(" Is64BitInstruction: {}\n", hdr.getIs64BitInstructionFlag());
std::cout << " ProcessAddressSpace: " << nn::hac::MetaUtil::getProcessAddressSpaceAsString(hdr.getProcessAddressSpace()) << std::endl; fmt::print(" ProcessAddressSpace: {:s}\n", nn::hac::MetaUtil::getProcessAddressSpaceAsString(hdr.getProcessAddressSpace()));
std::cout << " OptimizeMemoryAllocation: " << std::boolalpha << hdr.getOptimizeMemoryAllocationFlag() << std::endl; fmt::print(" OptimizeMemoryAllocation: {}\n", hdr.getOptimizeMemoryAllocationFlag());
std::cout << " SystemResourceSize: 0x" << std::hex << hdr.getSystemResourceSize() << std::endl; fmt::print(" SystemResourceSize: 0x{:x}\n", hdr.getSystemResourceSize());
std::cout << " Main Thread Params:" << std::endl; fmt::print(" Main Thread Params:\n");
std::cout << " Priority: " << std::dec << (uint32_t)hdr.getMainThreadPriority() << std::endl; fmt::print(" Priority: {:d}\n", hdr.getMainThreadPriority());
std::cout << " CpuId: " << std::dec << (uint32_t)hdr.getMainThreadCpuId() << std::endl; fmt::print(" CpuId: {:d}\n", hdr.getMainThreadCpuId());
std::cout << " StackSize: 0x" << std::hex << hdr.getMainThreadStackSize() << std::endl; fmt::print(" StackSize: 0x{:x}\n", hdr.getMainThreadStackSize());
std::cout << " TitleInfo:" << std::endl; fmt::print(" TitleInfo:\n");
std::cout << " Version: v" << std::dec << hdr.getVersion() << std::endl; fmt::print(" Version: v{:d}\n", hdr.getVersion());
std::cout << " Name: " << hdr.getName() << std::endl; fmt::print(" Name: {:s}\n", hdr.getName());
if (hdr.getProductCode().length()) if (hdr.getProductCode().length())
{ {
std::cout << " ProductCode: " << hdr.getProductCode() << std::endl; fmt::print(" ProductCode: {:s}\n", hdr.getProductCode());
} }
} }
void nstool::MetaProcess::displayAciHdr(const nn::hac::AccessControlInfo& aci) void nstool::MetaProcess::displayAciHdr(const nn::hac::AccessControlInfo& aci)
{ {
std::cout << "[Access Control Info]" << std::endl; fmt::print("[Access Control Info]\n");
std::cout << " ProgramID: 0x" << std::hex << std::setw(16) << std::setfill('0') << aci.getProgramId() << std::endl; fmt::print(" ProgramID: 0x{:016x}\n", aci.getProgramId());
} }
void nstool::MetaProcess::displayAciDescHdr(const nn::hac::AccessControlInfoDesc& acid) void nstool::MetaProcess::displayAciDescHdr(const nn::hac::AccessControlInfoDesc& acid)
{ {
std::cout << "[Access Control Info Desc]" << std::endl; fmt::print("[Access Control Info Desc]\n");
std::cout << " Flags: " << std::endl; fmt::print(" Flags: \n");
std::cout << " Production: " << std::boolalpha << acid.getProductionFlag() << std::endl; fmt::print(" Production: {}\n", acid.getProductionFlag());
std::cout << " Unqualified Approval: " << std::boolalpha << acid.getUnqualifiedApprovalFlag() << std::endl; fmt::print(" Unqualified Approval: {}\n", acid.getUnqualifiedApprovalFlag());
std::cout << " Memory Region: " << nn::hac::AccessControlInfoUtil::getMemoryRegionAsString(acid.getMemoryRegion()) << " (" << std::dec << (uint32_t)acid.getMemoryRegion() << ")" << std::endl; fmt::print(" Memory Region: {:s} ({:d})\n", nn::hac::AccessControlInfoUtil::getMemoryRegionAsString(acid.getMemoryRegion()), acid.getMemoryRegion());
std::cout << " ProgramID Restriction" << std::endl; fmt::print(" ProgramID Restriction\n");
std::cout << " Min: 0x" << std::hex << std::setw(16) << std::setfill('0') << acid.getProgramIdRestrict().min << std::endl; fmt::print(" Min: 0x{:016x}\n", acid.getProgramIdRestrict().min);
std::cout << " Max: 0x" << std::hex << std::setw(16) << std::setfill('0') << acid.getProgramIdRestrict().max << std::endl; fmt::print(" Max: 0x{:016x}\n", acid.getProgramIdRestrict().max);
} }
void nstool::MetaProcess::displayFac(const nn::hac::FileSystemAccessControl& fac) void nstool::MetaProcess::displayFac(const nn::hac::FileSystemAccessControl& fac)
{ {
std::cout << "[FS Access Control]" << std::endl; fmt::print("[FS Access Control]\n");
std::cout << " Format Version: " << std::dec << (uint32_t)fac.getFormatVersion() << std::endl; fmt::print(" Format Version: {:d}\n", fac.getFormatVersion());
auto fs_access = fac.getFsAccess(); if (fac.getFsAccess().size())
if (fs_access.any())
{ {
std::cout << " FsAccess:" << std::endl; std::vector<std::string> fs_access_str_list;
// TODO this formatting loop could be a utils function for (auto itr = fac.getFsAccess().begin(); itr != fac.getFsAccess().end(); itr++)
for (size_t flag = 0, printed = 0; flag < fs_access.size(); flag++)
{ {
// skip unset flags std::string flag_string = nn::hac::FileSystemAccessUtil::getFsAccessFlagAsString(nn::hac::fac::FsAccessFlag(*itr));
if (fs_access.test(flag) == false) if (mCliOutputMode.show_extended_info)
continue;
// format the strings
// for each 10 printed we do a new line
if (printed % 10 == 0)
{ {
// skip new line when we haven't printed anything fs_access_str_list.push_back(fmt::format("{:s} (bit {:d})", flag_string, *itr));
if (printed != 0)
std::cout << std::endl;
std::cout << " ";
} }
// within a line we want to separate the next string from the last one with a comma and a space
else else
{ {
std::cout << ", "; fs_access_str_list.push_back(flag_string);
} }
printed++;
// output string info
std::cout << nn::hac::FileSystemAccessUtil::getFsAccessFlagAsString(nn::hac::fac::FsAccessFlag(flag));
if (mCliOutputMode.show_extended_info)
std::cout << " (bit " << std::dec << (uint32_t)flag << ")";
} }
std::cout << std::endl;
fmt::print(" FsAccess:\n");
fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(fs_access_str_list, 60, 4));
} }
if (fac.getContentOwnerIdList().size()) if (fac.getContentOwnerIdList().size())
{ {
std::cout << " Content Owner IDs:" << std::endl; fmt::print(" Content Owner IDs:\n");
for (size_t i = 0; i < fac.getContentOwnerIdList().size(); i++) for (size_t i = 0; i < fac.getContentOwnerIdList().size(); i++)
{ {
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << fac.getContentOwnerIdList()[i] << std::endl; fmt::print(" 0x{:016x}\n", fac.getContentOwnerIdList()[i]);
} }
} }
if (fac.getSaveDataOwnerIdList().size()) if (fac.getSaveDataOwnerIdList().size())
{ {
std::cout << " Save Data Owner IDs:" << std::endl; fmt::print(" Save Data Owner IDs:\n");
for (size_t i = 0; i < fac.getSaveDataOwnerIdList().size(); i++) for (size_t i = 0; i < fac.getSaveDataOwnerIdList().size(); i++)
{ {
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << fac.getSaveDataOwnerIdList()[i].id << " (" << nn::hac::FileSystemAccessUtil::getSaveDataOwnerAccessModeAsString(fac.getSaveDataOwnerIdList()[i].access_type) << ")" << std::endl; fmt::print(" 0x{:016x} ({:s})\n", fac.getSaveDataOwnerIdList()[i].id, nn::hac::FileSystemAccessUtil::getSaveDataOwnerAccessModeAsString(fac.getSaveDataOwnerIdList()[i].access_type));
} }
} }
} }
void nstool::MetaProcess::displaySac(const nn::hac::ServiceAccessControl& sac) void nstool::MetaProcess::displaySac(const nn::hac::ServiceAccessControl& sac)
{ {
std::cout << "[Service Access Control]" << std::endl; fmt::print("[Service Access Control]\n");
std::cout << " Service List:" << std::endl; fmt::print(" Service List:\n");
std::vector<std::string> service_name_list; std::vector<std::string> service_name_list;
for (size_t i = 0; i < sac.getServiceList().size(); i++) for (size_t i = 0; i < sac.getServiceList().size(); i++)
{ {
service_name_list.push_back(sac.getServiceList()[i].getName() + (sac.getServiceList()[i].isServer() ? "(isSrv)" : "")); service_name_list.push_back(sac.getServiceList()[i].getName() + (sac.getServiceList()[i].isServer() ? "(isSrv)" : ""));
} }
fnd::SimpleTextOutput::dumpStringList(service_name_list, 60, 4); fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(service_name_list, 60, 4));
} }
void nstool::MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern) void nstool::MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
{ {
std::cout << "[Kernel Capabilities]" << std::endl; fmt::print("[Kernel Capabilities]\n");
if (kern.getThreadInfo().isSet()) if (kern.getThreadInfo().isSet())
{ {
nn::hac::ThreadInfoHandler threadInfo = kern.getThreadInfo(); nn::hac::ThreadInfoHandler threadInfo = kern.getThreadInfo();
std::cout << " Thread Priority:" << std::endl; fmt::print(" Thread Priority:\n");
std::cout << " Min: " << std::dec << (uint32_t)threadInfo.getMinPriority() << std::endl; fmt::print(" Min: {:d}\n", threadInfo.getMinPriority());
std::cout << " Max: " << std::dec << (uint32_t)threadInfo.getMaxPriority() << std::endl; fmt::print(" Max: {:d}\n", threadInfo.getMaxPriority());
std::cout << " CpuId:" << std::endl; fmt::print(" CpuId:\n");
std::cout << " Min: " << std::dec << (uint32_t)threadInfo.getMinCpuId() << std::endl; fmt::print(" Min: {:d}\n", threadInfo.getMinCpuId());
std::cout << " Max: " << std::dec << (uint32_t)threadInfo.getMaxCpuId() << std::endl; fmt::print(" Max: {:d}\n", threadInfo.getMaxCpuId());
} }
if (kern.getSystemCalls().isSet()) if (kern.getSystemCalls().isSet())
{ {
auto syscall_ids = kern.getSystemCalls().getSystemCallIds(); auto syscall_ids = kern.getSystemCalls().getSystemCallIds();
std::cout << " SystemCalls:" << std::endl; fmt::print(" SystemCalls:\n");
std::vector<std::string> syscall_names; std::vector<std::string> syscall_names;
for (size_t syscall_id = 0; syscall_id < syscall_ids.size(); syscall_id++) for (size_t syscall_id = 0; syscall_id < syscall_ids.size(); syscall_id++)
{ {
if (syscall_ids.test(syscall_id)) if (syscall_ids.test(syscall_id))
syscall_names.push_back(nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(syscall_id))); syscall_names.push_back(nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(syscall_id)));
} }
fnd::SimpleTextOutput::dumpStringList(syscall_names, 60, 4); fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(syscall_names, 60, 4));
} }
if (kern.getMemoryMaps().isSet()) if (kern.getMemoryMaps().isSet())
{ {
auto maps = kern.getMemoryMaps().getMemoryMaps(); auto maps = kern.getMemoryMaps().getMemoryMaps();
auto ioMaps = kern.getMemoryMaps().getIoMemoryMaps(); auto ioMaps = kern.getMemoryMaps().getIoMemoryMaps();
std::cout << " MemoryMaps:" << std::endl; fmt::print(" MemoryMaps:\n");
for (size_t i = 0; i < maps.size(); i++) for (size_t i = 0; i < maps.size(); i++)
{ {
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)maps[i].addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(maps[i].addr + maps[i].size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemoryPermissionAsString(maps[i].perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMappingTypeAsString(maps[i].type) << ")" << std::endl; fmt::print(" {:s}\n", formatMappingAsString(maps[i]));
} }
//std::cout << " IoMaps:" << std::endl; //fmt::print(" IoMaps:\n");
for (size_t i = 0; i < ioMaps.size(); i++) for (size_t i = 0; i < ioMaps.size(); i++)
{ {
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)ioMaps[i].addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(ioMaps[i].addr + ioMaps[i].size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemoryPermissionAsString(ioMaps[i].perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMappingTypeAsString(ioMaps[i].type) << ")" << std::endl; fmt::print(" {:s}\n", formatMappingAsString(ioMaps[i]));
} }
} }
if (kern.getInterupts().isSet()) if (kern.getInterupts().isSet())
{ {
std::vector<uint16_t> interupts = kern.getInterupts().getInteruptList(); std::vector<std::string> interupts;
std::cout << " Interupts Flags:" << std::endl; for (auto itr = kern.getInterupts().getInteruptList().begin(); itr != kern.getInterupts().getInteruptList().end(); itr++)
for (uint32_t i = 0; i < interupts.size(); i++)
{ {
if (i % 10 == 0) interupts.push_back(fmt::format("0x{:x}", *itr));
{
if (i != 0)
std::cout << std::endl;
std::cout << " ";
}
std::cout << "0x" << std::hex << (uint32_t)interupts[i];
if (interupts[i] != interupts.atBack())
std::cout << ", ";
} }
std::cout << std::endl; fmt::print(" Interupts Flags:\n");
fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(interupts, 60, 4));
} }
if (kern.getMiscParams().isSet()) if (kern.getMiscParams().isSet())
{ {
std::cout << " ProgramType: " << nn::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()) << " (" << std::dec << (uint32_t)kern.getMiscParams().getProgramType() << ")" << std::endl; fmt::print(" ProgramType: {:s} ({:d})\n", nn::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()), kern.getMiscParams().getProgramType());
} }
if (kern.getKernelVersion().isSet()) if (kern.getKernelVersion().isSet())
{ {
std::cout << " Kernel Version: " << std::dec << (uint32_t)kern.getKernelVersion().getVerMajor() << "." << (uint32_t)kern.getKernelVersion().getVerMinor() << std::endl; fmt::print(" Kernel Version: {:d}.{:d}\n", kern.getKernelVersion().getVerMajor(), kern.getKernelVersion().getVerMinor());
} }
if (kern.getHandleTableSize().isSet()) if (kern.getHandleTableSize().isSet())
{ {
std::cout << " Handle Table Size: 0x" << std::hex << kern.getHandleTableSize().getHandleTableSize() << std::endl; fmt::print(" Handle Table Size: 0x{:x}\n", kern.getHandleTableSize().getHandleTableSize());
} }
if (kern.getMiscFlags().isSet()) if (kern.getMiscFlags().isSet())
{ {
auto misc_flags = kern.getMiscFlags().getMiscFlags(); auto misc_flags = kern.getMiscFlags().getMiscFlags();
std::cout << " Misc Flags:" << std::endl; fmt::print(" Misc Flags:\n");
std::vector<std::string> misc_flags_names; std::vector<std::string> misc_flags_names;
for (size_t misc_flags_bit = 0; misc_flags_bit < misc_flags.size(); misc_flags_bit++) for (size_t misc_flags_bit = 0; misc_flags_bit < misc_flags.size(); misc_flags_bit++)
{ {
if (misc_flags.test(misc_flags_bit)) if (misc_flags.test(misc_flags_bit))
misc_flags_names.push_back(nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(misc_flags_bit))); misc_flags_names.push_back(nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(misc_flags_bit)));
} }
fnd::SimpleTextOutput::dumpStringList(misc_flags_names, 60, 4); fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(misc_flags_names, 60, 4));
} }
} }
std::string nstool::MetaProcess::formatMappingAsString(const nn::hac::MemoryMappingHandler::sMemoryMapping& map) const
{
return fmt::format("0x{:016x} - 0x{:016x} (perm={:s}) (type={:s})", ((uint64_t)map.addr << 12), (((uint64_t)(map.addr + map.size) << 12) - 1), nn::hac::KernelCapabilityUtil::getMemoryPermissionAsString(map.perm), nn::hac::KernelCapabilityUtil::getMappingTypeAsString(map.type));
}

View file

@ -21,7 +21,7 @@ public:
const nn::hac::Meta& getMeta() const; const nn::hac::Meta& getMeta() const;
private: private:
const std::string kModuleName = "MetaProcess"; std::string mModuleName;
std::shared_ptr<tc::io::IStream> mFile; std::shared_ptr<tc::io::IStream> mFile;
KeyBag mKeyCfg; KeyBag mKeyCfg;
@ -41,6 +41,8 @@ private:
void displayFac(const nn::hac::FileSystemAccessControl& fac); void displayFac(const nn::hac::FileSystemAccessControl& fac);
void displaySac(const nn::hac::ServiceAccessControl& sac); void displaySac(const nn::hac::ServiceAccessControl& sac);
void displayKernelCap(const nn::hac::KernelCapabilityControl& kern); void displayKernelCap(const nn::hac::KernelCapabilityControl& kern);
std::string formatMappingAsString(const nn::hac::MemoryMappingHandler::sMemoryMapping& map) const;
}; };
} }

View file

@ -7,7 +7,7 @@
#include "PfsProcess.h" #include "PfsProcess.h"
#include "RomfsProcess.h" #include "RomfsProcess.h"
//#include "NcaProcess.h" //#include "NcaProcess.h"
//#include "MetaProcess.h" #include "MetaProcess.h"
#include "CnmtProcess.h" #include "CnmtProcess.h"
#include "NsoProcess.h" #include "NsoProcess.h"
#include "NroProcess.h" #include "NroProcess.h"
@ -93,6 +93,7 @@ int umain(const std::vector<std::string>& args, const std::vector<std::string>&
obj.process(); obj.process();
} }
*/
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_META) else if (set.infile.filetype == nstool::Settings::FILE_TYPE_META)
{ {
nstool::MetaProcess obj; nstool::MetaProcess obj;
@ -104,7 +105,6 @@ int umain(const std::vector<std::string>& args, const std::vector<std::string>&
obj.process(); obj.process();
} }
*/
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_CNMT) else if (set.infile.filetype == nstool::Settings::FILE_TYPE_CNMT)
{ {
nstool::CnmtProcess obj; nstool::CnmtProcess obj;