mirror of
https://github.com/jakcron/nstool.git
synced 2024-12-22 18:55:29 +00:00
Port IniProcess & KipProcess to libtoolchain.
This commit is contained in:
parent
afd1c97272
commit
defccc6ddf
|
@ -1,5 +1,6 @@
|
||||||
#include "IniProcess.h"
|
#include "IniProcess.h"
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
#include "KipProcess.h"
|
#include "KipProcess.h"
|
||||||
|
|
||||||
nstool::IniProcess::IniProcess() :
|
nstool::IniProcess::IniProcess() :
|
||||||
|
@ -58,10 +59,9 @@ void nstool::IniProcess::importHeader()
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if file_size is smaller than INI header size
|
// check if file_size is smaller than INI header size
|
||||||
size_t file_size = tc::io::IOUtil::castInt64ToSize(mFile->length());
|
if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(nn::hac::sIniHeader))
|
||||||
if (file_size < sizeof(nn::hac::sIniHeader))
|
|
||||||
{
|
{
|
||||||
throw tc::Exception(mModuleName, "Corrupt NSO: file too small.");
|
throw tc::Exception(mModuleName, "Corrupt INI: file too small.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// read ini
|
// read ini
|
||||||
|
@ -76,7 +76,7 @@ void nstool::IniProcess::importHeader()
|
||||||
void nstool::IniProcess::importKipList()
|
void nstool::IniProcess::importKipList()
|
||||||
{
|
{
|
||||||
// kip pos info
|
// kip pos info
|
||||||
int64_t kip_pos = sizeof(nn::hac::sIniHeader);
|
int64_t kip_pos = tc::io::IOUtil::castSizeToInt64(sizeof(nn::hac::sIniHeader));
|
||||||
int64_t kip_size = 0;
|
int64_t kip_size = 0;
|
||||||
|
|
||||||
// tmp data to determine size
|
// tmp data to determine size
|
||||||
|
@ -89,7 +89,7 @@ void nstool::IniProcess::importKipList()
|
||||||
mFile->read((byte_t*)&hdr_raw, sizeof(hdr_raw));
|
mFile->read((byte_t*)&hdr_raw, sizeof(hdr_raw));
|
||||||
hdr.fromBytes((byte_t*)&hdr_raw, sizeof(hdr_raw));
|
hdr.fromBytes((byte_t*)&hdr_raw, sizeof(hdr_raw));
|
||||||
kip_size = getKipSizeFromHeader(hdr);
|
kip_size = getKipSizeFromHeader(hdr);
|
||||||
mKipList.push_back(std::make_shared<tc::io::SubStream>(tc::io::SubStream(mFile, kip_pos, kip_size)));
|
mKipList.push_back({hdr, std::make_shared<tc::io::SubStream>(tc::io::SubStream(mFile, kip_pos, kip_size))});
|
||||||
kip_pos += kip_size;
|
kip_pos += kip_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,11 +103,11 @@ void nstool::IniProcess::displayHeader()
|
||||||
|
|
||||||
void nstool::IniProcess::displayKipList()
|
void nstool::IniProcess::displayKipList()
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < mKipList.size(); i++)
|
for (auto itr = mKipList.begin(); itr != mKipList.end(); itr++)
|
||||||
{
|
{
|
||||||
KipProcess obj;
|
KipProcess obj;
|
||||||
|
|
||||||
obj.setInputFile(mKipList[i]);
|
obj.setInputFile(itr->stream);
|
||||||
obj.setCliOutputMode(mCliOutputMode);
|
obj.setCliOutputMode(mCliOutputMode);
|
||||||
obj.setVerifyMode(mVerify);
|
obj.setVerifyMode(mVerify);
|
||||||
|
|
||||||
|
@ -117,53 +117,34 @@ void nstool::IniProcess::displayKipList()
|
||||||
|
|
||||||
void nstool::IniProcess::extractKipList()
|
void nstool::IniProcess::extractKipList()
|
||||||
{
|
{
|
||||||
tc::ByteData cache;
|
|
||||||
nn::hac::KernelInitialProcessHeader hdr;
|
|
||||||
|
|
||||||
|
|
||||||
// allocate cache memory
|
// allocate cache memory
|
||||||
cache = tc::ByteData(kCacheSize);
|
tc::ByteData cache = tc::ByteData(kCacheSize);
|
||||||
|
|
||||||
// make extract dir
|
// make extract dir
|
||||||
fnd::io::makeDirectory(mKipExtractPath);
|
tc::io::LocalStorage local_fs;
|
||||||
|
local_fs.createDirectory(mKipExtractPath.get());
|
||||||
|
|
||||||
|
// out path for extracted KIP
|
||||||
|
tc::io::Path out_path;
|
||||||
|
std::string out_path_str;
|
||||||
|
|
||||||
// outfile object for writing KIP
|
// extract KIPs
|
||||||
fnd::SimpleFile out_file;
|
for (auto itr = mKipList.begin(); itr != mKipList.end(); itr++)
|
||||||
std::string out_path;
|
|
||||||
size_t out_size;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < mKipList.size(); i++)
|
|
||||||
{
|
{
|
||||||
// read header
|
out_path = mKipExtractPath.get();
|
||||||
(*mKipList[i])->read(cache.data(), 0, cache.size());
|
out_path += fmt::format("{:s}.kip", itr->hdr.getName());
|
||||||
hdr.fromBytes(cache.data(), cache.size());
|
|
||||||
|
|
||||||
// generate path
|
tc::io::PathUtil::pathToUnixUTF8(out_path, out_path_str);
|
||||||
out_path.clear();
|
|
||||||
fnd::io::appendToPath(out_path, mKipExtractPath);
|
|
||||||
fnd::io::appendToPath(out_path, hdr.getName() + kKipExtention);
|
|
||||||
|
|
||||||
// open file
|
|
||||||
out_file.open(out_path, fnd::SimpleFile::Create);
|
|
||||||
|
|
||||||
// get kip file size
|
|
||||||
out_size = (*mKipList[i])->size();
|
|
||||||
// extract kip
|
|
||||||
if (mCliOutputMode.show_basic_info)
|
if (mCliOutputMode.show_basic_info)
|
||||||
printf("extract=[%s]\n", out_path.c_str());
|
fmt::print("Saving {:s}...\n", out_path_str);
|
||||||
|
|
||||||
(*mKipList[i])->seek(0);
|
writeStreamToFile(itr->stream, out_path, cache);
|
||||||
for (size_t j = 0; j < ((out_size / kCacheSize) + ((out_size % kCacheSize) != 0)); j++)
|
|
||||||
{
|
|
||||||
(*mKipList[i])->read(cache.data(), _MIN(out_size - (kCacheSize * j), kCacheSize));
|
|
||||||
out_file.write(cache.data(), _MIN(out_size - (kCacheSize * j), kCacheSize));
|
|
||||||
}
|
|
||||||
out_file.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t nstool::IniProcess::getKipSizeFromHeader(const nn::hac::KernelInitialProcessHeader& hdr) const
|
int64_t nstool::IniProcess::getKipSizeFromHeader(const nn::hac::KernelInitialProcessHeader& hdr) const
|
||||||
{
|
{
|
||||||
return sizeof(nn::hac::sKipHeader) + hdr.getTextSegmentInfo().file_layout.size + hdr.getRoSegmentInfo().file_layout.size + hdr.getDataSegmentInfo().file_layout.size;
|
// the order of elements in a KIP are sequential, there are no file offsets
|
||||||
|
return int64_t(sizeof(nn::hac::sKipHeader)) + int64_t(hdr.getTextSegmentInfo().file_layout.size + hdr.getRoSegmentInfo().file_layout.size + hdr.getDataSegmentInfo().file_layout.size);
|
||||||
}
|
}
|
|
@ -1,15 +1,11 @@
|
||||||
#include "KipProcess.h"
|
#include "KipProcess.h"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
|
|
||||||
#include <fnd/SimpleTextOutput.h>
|
|
||||||
#include <fnd/OffsetAdjustedIFile.h>
|
|
||||||
#include <fnd/Vec.h>
|
|
||||||
|
|
||||||
#include <nn/hac/KernelCapabilityUtil.h>
|
#include <nn/hac/KernelCapabilityUtil.h>
|
||||||
|
|
||||||
|
#include <tc/NotImplementedException.h>
|
||||||
|
|
||||||
nstool::KipProcess::KipProcess() :
|
nstool::KipProcess::KipProcess() :
|
||||||
|
mModuleName("nstool::KipProcess"),
|
||||||
mFile(),
|
mFile(),
|
||||||
mCliOutputMode(true, false, false, false),
|
mCliOutputMode(true, false, false, false),
|
||||||
mVerify(false)
|
mVerify(false)
|
||||||
|
@ -19,7 +15,7 @@ nstool::KipProcess::KipProcess():
|
||||||
void nstool::KipProcess::process()
|
void nstool::KipProcess::process()
|
||||||
{
|
{
|
||||||
importHeader();
|
importHeader();
|
||||||
//importCodeSegments();
|
//importCodeSegments(); // code segments not imported because compression not supported yet
|
||||||
if (mCliOutputMode.show_basic_info)
|
if (mCliOutputMode.show_basic_info)
|
||||||
{
|
{
|
||||||
displayHeader();
|
displayHeader();
|
||||||
|
@ -44,223 +40,234 @@ void nstool::KipProcess::setVerifyMode(bool verify)
|
||||||
|
|
||||||
void nstool::KipProcess::importHeader()
|
void nstool::KipProcess::importHeader()
|
||||||
{
|
{
|
||||||
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.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*mFile)->size() < sizeof(nn::hac::sKipHeader))
|
// check if file_size is smaller than KIP header size
|
||||||
|
if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(nn::hac::sKipHeader))
|
||||||
{
|
{
|
||||||
throw tc::Exception(kModuleName, "Corrupt KIP: file too small");
|
throw tc::Exception(mModuleName, "Corrupt KIP: file too small.");
|
||||||
}
|
}
|
||||||
|
|
||||||
scratch.alloc(sizeof(nn::hac::sKipHeader));
|
// read kip
|
||||||
(*mFile)->read(scratch.data(), 0, scratch.size());
|
tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sKipHeader));
|
||||||
|
mFile->seek(0, tc::io::SeekOrigin::Begin);
|
||||||
|
mFile->read(scratch.data(), scratch.size());
|
||||||
|
|
||||||
|
// parse kip header
|
||||||
mHdr.fromBytes(scratch.data(), scratch.size());
|
mHdr.fromBytes(scratch.data(), scratch.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void nstool::KipProcess::importCodeSegments()
|
void nstool::KipProcess::importCodeSegments()
|
||||||
{
|
{
|
||||||
#ifdef _KIP_COMPRESSION_IMPLEMENTED
|
|
||||||
tc::ByteData scratch;
|
tc::ByteData scratch;
|
||||||
uint32_t decompressed_len;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// process text segment
|
// process text segment
|
||||||
#ifdef _KIP_COMPRESSION_IMPLEMENTED
|
|
||||||
if (mHdr.getTextSegmentInfo().is_compressed)
|
if (mHdr.getTextSegmentInfo().is_compressed)
|
||||||
{
|
{
|
||||||
scratch.alloc(mHdr.getTextSegmentInfo().file_layout.size);
|
// allocate/read compressed text
|
||||||
(*mFile)->read(scratch.data(), mHdr.getTextSegmentInfo().file_layout.offset, scratch.size());
|
scratch = tc::ByteData(mHdr.getTextSegmentInfo().file_layout.size);
|
||||||
mTextBlob.alloc(mHdr.getTextSegmentInfo().memory_layout.size);
|
mFile->seek(mHdr.getTextSegmentInfo().file_layout.offset, tc::io::SeekOrigin::Begin);
|
||||||
fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mTextBlob.data(), (uint32_t)mTextBlob.size(), decompressed_len);
|
mFile->read(scratch.data(), scratch.size());
|
||||||
if (decompressed_len != mTextBlob.size())
|
|
||||||
|
// allocate for decompressed text segment
|
||||||
|
mTextBlob = tc::ByteData(mHdr.getTextSegmentInfo().memory_layout.size);
|
||||||
|
|
||||||
|
// decompress text segment
|
||||||
|
if (decompressData(scratch.data(), scratch.size(), mTextBlob.data(), mTextBlob.size()) != mTextBlob.size())
|
||||||
{
|
{
|
||||||
throw tc::Exception(kModuleName, "KIP text segment failed to decompress");
|
throw tc::Exception(mModuleName, "KIP text segment failed to decompress");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mTextBlob.alloc(mHdr.getTextSegmentInfo().file_layout.size);
|
// read text segment directly (not compressed)
|
||||||
(*mFile)->read(mTextBlob.data(), mHdr.getTextSegmentInfo().file_layout.offset, mTextBlob.size());
|
mTextBlob = tc::ByteData(mHdr.getTextSegmentInfo().file_layout.size);
|
||||||
|
mFile->seek(mHdr.getTextSegmentInfo().file_layout.offset, tc::io::SeekOrigin::Begin);
|
||||||
|
mFile->read(mTextBlob.data(), mTextBlob.size());
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
mTextBlob.alloc(mHdr.getTextSegmentInfo().file_layout.size);
|
|
||||||
(*mFile)->read(mTextBlob.data(), mHdr.getTextSegmentInfo().file_layout.offset, mTextBlob.size());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// process ro segment
|
// process ro segment
|
||||||
#ifdef _KIP_COMPRESSION_IMPLEMENTED
|
|
||||||
if (mHdr.getRoSegmentInfo().is_compressed)
|
if (mHdr.getRoSegmentInfo().is_compressed)
|
||||||
{
|
{
|
||||||
scratch.alloc(mHdr.getRoSegmentInfo().file_layout.size);
|
// allocate/read compressed ro segment
|
||||||
(*mFile)->read(scratch.data(), mHdr.getRoSegmentInfo().file_layout.offset, scratch.size());
|
scratch = tc::ByteData(mHdr.getRoSegmentInfo().file_layout.size);
|
||||||
mRoBlob.alloc(mHdr.getRoSegmentInfo().memory_layout.size);
|
mFile->seek(mHdr.getRoSegmentInfo().file_layout.offset, tc::io::SeekOrigin::Begin);
|
||||||
fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mRoBlob.data(), (uint32_t)mRoBlob.size(), decompressed_len);
|
mFile->read(scratch.data(), scratch.size());
|
||||||
if (decompressed_len != mRoBlob.size())
|
|
||||||
|
// allocate for decompressed ro segment
|
||||||
|
mRoBlob = tc::ByteData(mHdr.getRoSegmentInfo().memory_layout.size);
|
||||||
|
|
||||||
|
// decompress ro segment
|
||||||
|
if (decompressData(scratch.data(), scratch.size(), mRoBlob.data(), mRoBlob.size()) != mRoBlob.size())
|
||||||
{
|
{
|
||||||
throw tc::Exception(kModuleName, "KIP ro segment failed to decompress");
|
throw tc::Exception(mModuleName, "KIP ro segment failed to decompress");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mRoBlob.alloc(mHdr.getRoSegmentInfo().file_layout.size);
|
// read ro segment directly (not compressed)
|
||||||
(*mFile)->read(mRoBlob.data(), mHdr.getRoSegmentInfo().file_layout.offset, mRoBlob.size());
|
mRoBlob = tc::ByteData(mHdr.getRoSegmentInfo().file_layout.size);
|
||||||
|
mFile->seek(mHdr.getRoSegmentInfo().file_layout.offset, tc::io::SeekOrigin::Begin);
|
||||||
|
mFile->read(mRoBlob.data(), mRoBlob.size());
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
mRoBlob.alloc(mHdr.getRoSegmentInfo().file_layout.size);
|
|
||||||
(*mFile)->read(mRoBlob.data(), mHdr.getRoSegmentInfo().file_layout.offset, mRoBlob.size());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// process data segment
|
// process ro segment
|
||||||
#ifdef _KIP_COMPRESSION_IMPLEMENTED
|
|
||||||
if (mHdr.getDataSegmentInfo().is_compressed)
|
if (mHdr.getDataSegmentInfo().is_compressed)
|
||||||
{
|
{
|
||||||
scratch.alloc(mHdr.getDataSegmentInfo().file_layout.size);
|
// allocate/read compressed ro segment
|
||||||
(*mFile)->read(scratch.data(), mHdr.getDataSegmentInfo().file_layout.offset, scratch.size());
|
scratch = tc::ByteData(mHdr.getDataSegmentInfo().file_layout.size);
|
||||||
mDataBlob.alloc(mHdr.getDataSegmentInfo().memory_layout.size);
|
mFile->seek(mHdr.getDataSegmentInfo().file_layout.offset, tc::io::SeekOrigin::Begin);
|
||||||
fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mDataBlob.data(), (uint32_t)mDataBlob.size(), decompressed_len);
|
mFile->read(scratch.data(), scratch.size());
|
||||||
if (decompressed_len != mDataBlob.size())
|
|
||||||
|
// allocate for decompressed ro segment
|
||||||
|
mDataBlob = tc::ByteData(mHdr.getDataSegmentInfo().memory_layout.size);
|
||||||
|
|
||||||
|
// decompress ro segment
|
||||||
|
if (decompressData(scratch.data(), scratch.size(), mDataBlob.data(), mDataBlob.size()) != mDataBlob.size())
|
||||||
{
|
{
|
||||||
throw tc::Exception(kModuleName, "KIP data segment failed to decompress");
|
throw tc::Exception(mModuleName, "KIP data segment failed to decompress");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mDataBlob.alloc(mHdr.getDataSegmentInfo().file_layout.size);
|
// read ro segment directly (not compressed)
|
||||||
(*mFile)->read(mDataBlob.data(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.size());
|
mDataBlob = tc::ByteData(mHdr.getDataSegmentInfo().file_layout.size);
|
||||||
|
mFile->seek(mHdr.getDataSegmentInfo().file_layout.offset, tc::io::SeekOrigin::Begin);
|
||||||
|
mFile->read(mDataBlob.data(), mDataBlob.size());
|
||||||
}
|
}
|
||||||
#else
|
}
|
||||||
mDataBlob.alloc(mHdr.getDataSegmentInfo().file_layout.size);
|
|
||||||
(*mFile)->read(mDataBlob.data(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.size());
|
size_t nstool::KipProcess::decompressData(const byte_t* src, size_t src_len, byte_t* dst, size_t dst_capacity)
|
||||||
#endif
|
{
|
||||||
|
throw tc::NotImplementedException(mModuleName, "KIP decompression not implemented yet.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void nstool::KipProcess::displayHeader()
|
void nstool::KipProcess::displayHeader()
|
||||||
{
|
{
|
||||||
std::cout << "[KIP Header]" << std::endl;
|
fmt::print("[KIP Header]\n");
|
||||||
std::cout << " Meta:" << std::endl;
|
fmt::print(" Meta:\n");
|
||||||
std::cout << " Name: " << mHdr.getName() << std::endl;
|
fmt::print(" Name: {:s}\n", mHdr.getName());
|
||||||
std::cout << " TitleId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mHdr.getTitleId() << std::endl;
|
fmt::print(" TitleId: 0x{:016x}\n", mHdr.getTitleId());
|
||||||
std::cout << " Version: v" << std::dec << mHdr.getVersion() << std::endl;
|
fmt::print(" Version: v{:d}\n", mHdr.getVersion());
|
||||||
std::cout << " Is64BitInstruction: " << std::boolalpha << mHdr.getIs64BitInstructionFlag() << std::endl;
|
fmt::print(" Is64BitInstruction: {}\n", mHdr.getIs64BitInstructionFlag());
|
||||||
std::cout << " Is64BitAddressSpace: " << std::boolalpha << mHdr.getIs64BitAddressSpaceFlag() << std::endl;
|
fmt::print(" Is64BitAddressSpace: {}\n", mHdr.getIs64BitAddressSpaceFlag());
|
||||||
std::cout << " UseSecureMemory: " << std::boolalpha << mHdr.getUseSecureMemoryFlag() << std::endl;
|
fmt::print(" UseSecureMemory: {}\n", mHdr.getUseSecureMemoryFlag());
|
||||||
std::cout << " Program Sections:" << std::endl;
|
fmt::print(" Program Sections:\n");
|
||||||
std::cout << " .text:" << std::endl;
|
fmt::print(" .text:\n");
|
||||||
if (mCliOutputMode.show_layout)
|
if (mCliOutputMode.show_layout)
|
||||||
{
|
{
|
||||||
std::cout << " FileOffset: 0x" << std::hex << mHdr.getTextSegmentInfo().file_layout.offset << std::endl;
|
fmt::print(" FileOffset: 0x{:x}\n", mHdr.getTextSegmentInfo().file_layout.offset);
|
||||||
std::cout << " FileSize: 0x" << std::hex << mHdr.getTextSegmentInfo().file_layout.size << (mHdr.getTextSegmentInfo().is_compressed? " (COMPRESSED)" : "") << std::endl;
|
fmt::print(" FileSize: 0x{:x}{:s}\n", mHdr.getTextSegmentInfo().file_layout.size, (mHdr.getTextSegmentInfo().is_compressed? " (COMPRESSED)" : ""));
|
||||||
}
|
}
|
||||||
std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getTextSegmentInfo().memory_layout.offset << std::endl;
|
fmt::print(" MemoryOffset: 0x{:x}\n", mHdr.getTextSegmentInfo().memory_layout.offset);
|
||||||
std::cout << " MemorySize: 0x" << std::hex << mHdr.getTextSegmentInfo().memory_layout.size << std::endl;
|
fmt::print(" MemorySize: 0x{:x}\n", mHdr.getTextSegmentInfo().memory_layout.size);
|
||||||
std::cout << " .ro:" << std::endl;
|
fmt::print(" .ro:\n");
|
||||||
if (mCliOutputMode.show_layout)
|
if (mCliOutputMode.show_layout)
|
||||||
{
|
{
|
||||||
std::cout << " FileOffset: 0x" << std::hex << mHdr.getRoSegmentInfo().file_layout.offset << std::endl;
|
fmt::print(" FileOffset: 0x{:x}\n", mHdr.getRoSegmentInfo().file_layout.offset);
|
||||||
std::cout << " FileSize: 0x" << std::hex << mHdr.getRoSegmentInfo().file_layout.size << (mHdr.getRoSegmentInfo().is_compressed? " (COMPRESSED)" : "") << std::endl;
|
fmt::print(" FileSize: 0x{:x}{:s}\n", mHdr.getRoSegmentInfo().file_layout.size, (mHdr.getRoSegmentInfo().is_compressed? " (COMPRESSED)" : ""));
|
||||||
}
|
}
|
||||||
std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getRoSegmentInfo().memory_layout.offset << std::endl;
|
fmt::print(" MemoryOffset: 0x{:x}\n", mHdr.getRoSegmentInfo().memory_layout.offset);
|
||||||
std::cout << " MemorySize: 0x" << std::hex << mHdr.getRoSegmentInfo().memory_layout.size << std::endl;
|
fmt::print(" MemorySize: 0x{:x}\n", mHdr.getRoSegmentInfo().memory_layout.size);
|
||||||
std::cout << " .data:" << std::endl;
|
fmt::print(" .data:\n");
|
||||||
if (mCliOutputMode.show_layout)
|
if (mCliOutputMode.show_layout)
|
||||||
{
|
{
|
||||||
std::cout << " FileOffset: 0x" << std::hex << mHdr.getDataSegmentInfo().file_layout.offset << std::endl;
|
fmt::print(" FileOffset: 0x{:x}\n", mHdr.getDataSegmentInfo().file_layout.offset);
|
||||||
std::cout << " FileSize: 0x" << std::hex << mHdr.getDataSegmentInfo().file_layout.size << (mHdr.getDataSegmentInfo().is_compressed? " (COMPRESSED)" : "") << std::endl;
|
fmt::print(" FileSize: 0x{:x}{:s}\n", mHdr.getDataSegmentInfo().file_layout.size, (mHdr.getDataSegmentInfo().is_compressed? " (COMPRESSED)" : ""));
|
||||||
}
|
}
|
||||||
std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getDataSegmentInfo().memory_layout.offset << std::endl;
|
fmt::print(" MemoryOffset: 0x{:x}\n", mHdr.getDataSegmentInfo().memory_layout.offset);
|
||||||
std::cout << " MemorySize: 0x" << std::hex << mHdr.getDataSegmentInfo().memory_layout.size << std::endl;
|
fmt::print(" MemorySize: 0x{:x}\n", mHdr.getDataSegmentInfo().memory_layout.size);
|
||||||
std::cout << " .bss:" << std::endl;
|
fmt::print(" .bss:\n");
|
||||||
std::cout << " MemorySize: 0x" << std::hex << mHdr.getBssSize() << std::endl;
|
fmt::print(" MemorySize: 0x{:x}\n", mHdr.getBssSize());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nstool::KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
|
void nstool::KipProcess::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())
|
||||||
{
|
{
|
||||||
std::vector<nn::hac::MemoryMappingHandler::sMemoryMapping> maps = kern.getMemoryMaps().getMemoryMaps();
|
auto maps = kern.getMemoryMaps().getMemoryMaps();
|
||||||
std::vector<nn::hac::MemoryMappingHandler::sMemoryMapping> 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];
|
fmt::print(" Interupts Flags:\n");
|
||||||
if (interupts[i] != interupts.atBack())
|
fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(interupts, 60, 4));
|
||||||
std::cout << ", ";
|
|
||||||
}
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
}
|
||||||
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::KipProcess::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));
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ public:
|
||||||
void setCliOutputMode(CliOutputMode type);
|
void setCliOutputMode(CliOutputMode type);
|
||||||
void setVerifyMode(bool verify);
|
void setVerifyMode(bool verify);
|
||||||
private:
|
private:
|
||||||
const std::string kModuleName = "KipProcess";
|
std::string mModuleName;
|
||||||
|
|
||||||
std::shared_ptr<tc::io::IStream> mFile;
|
std::shared_ptr<tc::io::IStream> mFile;
|
||||||
CliOutputMode mCliOutputMode;
|
CliOutputMode mCliOutputMode;
|
||||||
|
@ -27,8 +27,11 @@ private:
|
||||||
|
|
||||||
void importHeader();
|
void importHeader();
|
||||||
void importCodeSegments();
|
void importCodeSegments();
|
||||||
|
size_t decompressData(const byte_t* src, size_t src_len, byte_t* dst, size_t dst_capacity);
|
||||||
void displayHeader();
|
void displayHeader();
|
||||||
void displayKernelCap(const nn::hac::KernelCapabilityControl& kern);
|
void displayKernelCap(const nn::hac::KernelCapabilityControl& kern);
|
||||||
|
|
||||||
|
std::string formatMappingAsString(const nn::hac::MemoryMappingHandler::sMemoryMapping& map) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue