diff --git a/src/IniProcess.cpp b/src/IniProcess.cpp index 38a2222..cf329c8 100644 --- a/src/IniProcess.cpp +++ b/src/IniProcess.cpp @@ -1,5 +1,6 @@ #include "IniProcess.h" +#include "util.h" #include "KipProcess.h" nstool::IniProcess::IniProcess() : @@ -58,10 +59,9 @@ void nstool::IniProcess::importHeader() } // check if file_size is smaller than INI header size - size_t file_size = tc::io::IOUtil::castInt64ToSize(mFile->length()); - if (file_size < sizeof(nn::hac::sIniHeader)) + if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(nn::hac::sIniHeader)) { - throw tc::Exception(mModuleName, "Corrupt NSO: file too small."); + throw tc::Exception(mModuleName, "Corrupt INI: file too small."); } // read ini @@ -76,7 +76,7 @@ void nstool::IniProcess::importHeader() void nstool::IniProcess::importKipList() { // 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; // tmp data to determine size @@ -89,7 +89,7 @@ void nstool::IniProcess::importKipList() mFile->read((byte_t*)&hdr_raw, sizeof(hdr_raw)); hdr.fromBytes((byte_t*)&hdr_raw, sizeof(hdr_raw)); kip_size = getKipSizeFromHeader(hdr); - mKipList.push_back(std::make_shared(tc::io::SubStream(mFile, kip_pos, kip_size))); + mKipList.push_back({hdr, std::make_shared(tc::io::SubStream(mFile, kip_pos, kip_size))}); kip_pos += kip_size; } } @@ -103,11 +103,11 @@ void nstool::IniProcess::displayHeader() void nstool::IniProcess::displayKipList() { - for (size_t i = 0; i < mKipList.size(); i++) + for (auto itr = mKipList.begin(); itr != mKipList.end(); itr++) { KipProcess obj; - obj.setInputFile(mKipList[i]); + obj.setInputFile(itr->stream); obj.setCliOutputMode(mCliOutputMode); obj.setVerifyMode(mVerify); @@ -117,53 +117,34 @@ void nstool::IniProcess::displayKipList() void nstool::IniProcess::extractKipList() { - tc::ByteData cache; - nn::hac::KernelInitialProcessHeader hdr; - - // allocate cache memory - cache = tc::ByteData(kCacheSize); + tc::ByteData cache = tc::ByteData(kCacheSize); // make extract dir - fnd::io::makeDirectory(mKipExtractPath); - + tc::io::LocalStorage local_fs; + local_fs.createDirectory(mKipExtractPath.get()); - // outfile object for writing KIP - fnd::SimpleFile out_file; - std::string out_path; - size_t out_size; + // out path for extracted KIP + tc::io::Path out_path; + std::string out_path_str; - for (size_t i = 0; i < mKipList.size(); i++) + // extract KIPs + for (auto itr = mKipList.begin(); itr != mKipList.end(); itr++) { - // read header - (*mKipList[i])->read(cache.data(), 0, cache.size()); - hdr.fromBytes(cache.data(), cache.size()); + out_path = mKipExtractPath.get(); + out_path += fmt::format("{:s}.kip", itr->hdr.getName()); - // generate path - out_path.clear(); - fnd::io::appendToPath(out_path, mKipExtractPath); - fnd::io::appendToPath(out_path, hdr.getName() + kKipExtention); + tc::io::PathUtil::pathToUnixUTF8(out_path, out_path_str); - // 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) - printf("extract=[%s]\n", out_path.c_str()); + fmt::print("Saving {:s}...\n", out_path_str); - (*mKipList[i])->seek(0); - 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(); + writeStreamToFile(itr->stream, out_path, cache); } } 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); } \ No newline at end of file diff --git a/src/KipProcess.cpp b/src/KipProcess.cpp index dbaae88..2b7468b 100644 --- a/src/KipProcess.cpp +++ b/src/KipProcess.cpp @@ -1,15 +1,11 @@ #include "KipProcess.h" -#include -#include - -#include -#include -#include - #include -nstool::KipProcess::KipProcess(): +#include + +nstool::KipProcess::KipProcess() : + mModuleName("nstool::KipProcess"), mFile(), mCliOutputMode(true, false, false, false), mVerify(false) @@ -19,7 +15,7 @@ nstool::KipProcess::KipProcess(): void nstool::KipProcess::process() { importHeader(); - //importCodeSegments(); + //importCodeSegments(); // code segments not imported because compression not supported yet if (mCliOutputMode.show_basic_info) { displayHeader(); @@ -44,223 +40,234 @@ void nstool::KipProcess::setVerifyMode(bool verify) 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)); - (*mFile)->read(scratch.data(), 0, scratch.size()); + // read kip + 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()); } void nstool::KipProcess::importCodeSegments() { -#ifdef _KIP_COMPRESSION_IMPLEMENTED tc::ByteData scratch; - uint32_t decompressed_len; -#endif // process text segment -#ifdef _KIP_COMPRESSION_IMPLEMENTED if (mHdr.getTextSegmentInfo().is_compressed) { - scratch.alloc(mHdr.getTextSegmentInfo().file_layout.size); - (*mFile)->read(scratch.data(), mHdr.getTextSegmentInfo().file_layout.offset, scratch.size()); - mTextBlob.alloc(mHdr.getTextSegmentInfo().memory_layout.size); - fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mTextBlob.data(), (uint32_t)mTextBlob.size(), decompressed_len); - if (decompressed_len != mTextBlob.size()) + // allocate/read compressed text + scratch = tc::ByteData(mHdr.getTextSegmentInfo().file_layout.size); + mFile->seek(mHdr.getTextSegmentInfo().file_layout.offset, tc::io::SeekOrigin::Begin); + mFile->read(scratch.data(), scratch.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 { - mTextBlob.alloc(mHdr.getTextSegmentInfo().file_layout.size); - (*mFile)->read(mTextBlob.data(), mHdr.getTextSegmentInfo().file_layout.offset, mTextBlob.size()); + // read text segment directly (not compressed) + 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 -#ifdef _KIP_COMPRESSION_IMPLEMENTED if (mHdr.getRoSegmentInfo().is_compressed) { - scratch.alloc(mHdr.getRoSegmentInfo().file_layout.size); - (*mFile)->read(scratch.data(), mHdr.getRoSegmentInfo().file_layout.offset, scratch.size()); - mRoBlob.alloc(mHdr.getRoSegmentInfo().memory_layout.size); - fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mRoBlob.data(), (uint32_t)mRoBlob.size(), decompressed_len); - if (decompressed_len != mRoBlob.size()) + // allocate/read compressed ro segment + scratch = tc::ByteData(mHdr.getRoSegmentInfo().file_layout.size); + mFile->seek(mHdr.getRoSegmentInfo().file_layout.offset, tc::io::SeekOrigin::Begin); + mFile->read(scratch.data(), scratch.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 { - mRoBlob.alloc(mHdr.getRoSegmentInfo().file_layout.size); - (*mFile)->read(mRoBlob.data(), mHdr.getRoSegmentInfo().file_layout.offset, mRoBlob.size()); + // read ro segment directly (not compressed) + 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 -#ifdef _KIP_COMPRESSION_IMPLEMENTED + // process ro segment if (mHdr.getDataSegmentInfo().is_compressed) { - scratch.alloc(mHdr.getDataSegmentInfo().file_layout.size); - (*mFile)->read(scratch.data(), mHdr.getDataSegmentInfo().file_layout.offset, scratch.size()); - mDataBlob.alloc(mHdr.getDataSegmentInfo().memory_layout.size); - fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mDataBlob.data(), (uint32_t)mDataBlob.size(), decompressed_len); - if (decompressed_len != mDataBlob.size()) + // allocate/read compressed ro segment + scratch = tc::ByteData(mHdr.getDataSegmentInfo().file_layout.size); + mFile->seek(mHdr.getDataSegmentInfo().file_layout.offset, tc::io::SeekOrigin::Begin); + mFile->read(scratch.data(), scratch.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 { - mDataBlob.alloc(mHdr.getDataSegmentInfo().file_layout.size); - (*mFile)->read(mDataBlob.data(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.size()); + // read ro segment directly (not compressed) + 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()); -#endif +} + +size_t nstool::KipProcess::decompressData(const byte_t* src, size_t src_len, byte_t* dst, size_t dst_capacity) +{ + throw tc::NotImplementedException(mModuleName, "KIP decompression not implemented yet."); } void nstool::KipProcess::displayHeader() { - std::cout << "[KIP Header]" << std::endl; - std::cout << " Meta:" << std::endl; - std::cout << " Name: " << mHdr.getName() << std::endl; - std::cout << " TitleId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mHdr.getTitleId() << std::endl; - std::cout << " Version: v" << std::dec << mHdr.getVersion() << std::endl; - std::cout << " Is64BitInstruction: " << std::boolalpha << mHdr.getIs64BitInstructionFlag() << std::endl; - std::cout << " Is64BitAddressSpace: " << std::boolalpha << mHdr.getIs64BitAddressSpaceFlag() << std::endl; - std::cout << " UseSecureMemory: " << std::boolalpha << mHdr.getUseSecureMemoryFlag() << std::endl; - std::cout << " Program Sections:" << std::endl; - std::cout << " .text:" << std::endl; + fmt::print("[KIP Header]\n"); + fmt::print(" Meta:\n"); + fmt::print(" Name: {:s}\n", mHdr.getName()); + fmt::print(" TitleId: 0x{:016x}\n", mHdr.getTitleId()); + fmt::print(" Version: v{:d}\n", mHdr.getVersion()); + fmt::print(" Is64BitInstruction: {}\n", mHdr.getIs64BitInstructionFlag()); + fmt::print(" Is64BitAddressSpace: {}\n", mHdr.getIs64BitAddressSpaceFlag()); + fmt::print(" UseSecureMemory: {}\n", mHdr.getUseSecureMemoryFlag()); + fmt::print(" Program Sections:\n"); + fmt::print(" .text:\n"); if (mCliOutputMode.show_layout) { - std::cout << " FileOffset: 0x" << std::hex << mHdr.getTextSegmentInfo().file_layout.offset << std::endl; - std::cout << " FileSize: 0x" << std::hex << mHdr.getTextSegmentInfo().file_layout.size << (mHdr.getTextSegmentInfo().is_compressed? " (COMPRESSED)" : "") << std::endl; + fmt::print(" FileOffset: 0x{:x}\n", mHdr.getTextSegmentInfo().file_layout.offset); + 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; - std::cout << " MemorySize: 0x" << std::hex << mHdr.getTextSegmentInfo().memory_layout.size << std::endl; - std::cout << " .ro:" << std::endl; + fmt::print(" MemoryOffset: 0x{:x}\n", mHdr.getTextSegmentInfo().memory_layout.offset); + fmt::print(" MemorySize: 0x{:x}\n", mHdr.getTextSegmentInfo().memory_layout.size); + fmt::print(" .ro:\n"); if (mCliOutputMode.show_layout) { - std::cout << " FileOffset: 0x" << std::hex << mHdr.getRoSegmentInfo().file_layout.offset << std::endl; - std::cout << " FileSize: 0x" << std::hex << mHdr.getRoSegmentInfo().file_layout.size << (mHdr.getRoSegmentInfo().is_compressed? " (COMPRESSED)" : "") << std::endl; + fmt::print(" FileOffset: 0x{:x}\n", mHdr.getRoSegmentInfo().file_layout.offset); + 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; - std::cout << " MemorySize: 0x" << std::hex << mHdr.getRoSegmentInfo().memory_layout.size << std::endl; - std::cout << " .data:" << std::endl; + fmt::print(" MemoryOffset: 0x{:x}\n", mHdr.getRoSegmentInfo().memory_layout.offset); + fmt::print(" MemorySize: 0x{:x}\n", mHdr.getRoSegmentInfo().memory_layout.size); + fmt::print(" .data:\n"); if (mCliOutputMode.show_layout) { - std::cout << " FileOffset: 0x" << std::hex << mHdr.getDataSegmentInfo().file_layout.offset << std::endl; - std::cout << " FileSize: 0x" << std::hex << mHdr.getDataSegmentInfo().file_layout.size << (mHdr.getDataSegmentInfo().is_compressed? " (COMPRESSED)" : "") << std::endl; + fmt::print(" FileOffset: 0x{:x}\n", mHdr.getDataSegmentInfo().file_layout.offset); + 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; - std::cout << " MemorySize: 0x" << std::hex << mHdr.getDataSegmentInfo().memory_layout.size << std::endl; - std::cout << " .bss:" << std::endl; - std::cout << " MemorySize: 0x" << std::hex << mHdr.getBssSize() << std::endl; + fmt::print(" MemoryOffset: 0x{:x}\n", mHdr.getDataSegmentInfo().memory_layout.offset); + fmt::print(" MemorySize: 0x{:x}\n", mHdr.getDataSegmentInfo().memory_layout.size); + fmt::print(" .bss:\n"); + fmt::print(" MemorySize: 0x{:x}\n", mHdr.getBssSize()); } void nstool::KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern) { - std::cout << "[Kernel Capabilities]" << std::endl; + fmt::print("[Kernel Capabilities]\n"); if (kern.getThreadInfo().isSet()) { nn::hac::ThreadInfoHandler threadInfo = kern.getThreadInfo(); - std::cout << " Thread Priority:" << std::endl; - std::cout << " Min: " << std::dec << (uint32_t)threadInfo.getMinPriority() << std::endl; - std::cout << " Max: " << std::dec << (uint32_t)threadInfo.getMaxPriority() << std::endl; - std::cout << " CpuId:" << std::endl; - std::cout << " Min: " << std::dec << (uint32_t)threadInfo.getMinCpuId() << std::endl; - std::cout << " Max: " << std::dec << (uint32_t)threadInfo.getMaxCpuId() << std::endl; + fmt::print(" Thread Priority:\n"); + fmt::print(" Min: {:d}\n", threadInfo.getMinPriority()); + fmt::print(" Max: {:d}\n", threadInfo.getMaxPriority()); + fmt::print(" CpuId:\n"); + fmt::print(" Min: {:d}\n", threadInfo.getMinCpuId()); + fmt::print(" Max: {:d}\n", threadInfo.getMaxCpuId()); } if (kern.getSystemCalls().isSet()) { auto syscall_ids = kern.getSystemCalls().getSystemCallIds(); - std::cout << " SystemCalls:" << std::endl; + fmt::print(" SystemCalls:\n"); std::vector syscall_names; for (size_t syscall_id = 0; syscall_id < syscall_ids.size(); syscall_id++) { if (syscall_ids.test(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()) { - std::vector maps = kern.getMemoryMaps().getMemoryMaps(); - std::vector ioMaps = kern.getMemoryMaps().getIoMemoryMaps(); + auto maps = kern.getMemoryMaps().getMemoryMaps(); + auto ioMaps = kern.getMemoryMaps().getIoMemoryMaps(); - std::cout << " MemoryMaps:" << std::endl; + fmt::print(" MemoryMaps:\n"); 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++) { - 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()) { - std::vector interupts = kern.getInterupts().getInteruptList(); - std::cout << " Interupts Flags:" << std::endl; - for (uint32_t i = 0; i < interupts.size(); i++) + std::vector interupts; + for (auto itr = kern.getInterupts().getInteruptList().begin(); itr != kern.getInterupts().getInteruptList().end(); itr++) { - if (i % 10 == 0) - { - 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 << ", "; + interupts.push_back(fmt::format("0x{:x}", *itr)); } - std::cout << std::endl; + fmt::print(" Interupts Flags:\n"); + fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(interupts, 60, 4)); } 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()) { - 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()) { - 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()) { auto misc_flags = kern.getMiscFlags().getMiscFlags(); - std::cout << " Misc Flags:" << std::endl; + fmt::print(" Misc Flags:\n"); std::vector misc_flags_names; for (size_t misc_flags_bit = 0; misc_flags_bit < misc_flags.size(); 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))); } - 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)); } \ No newline at end of file diff --git a/src/KipProcess.h b/src/KipProcess.h index cd844c9..b9bfd46 100644 --- a/src/KipProcess.h +++ b/src/KipProcess.h @@ -16,7 +16,7 @@ public: void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); private: - const std::string kModuleName = "KipProcess"; + std::string mModuleName; std::shared_ptr mFile; CliOutputMode mCliOutputMode; @@ -27,8 +27,11 @@ private: void importHeader(); void importCodeSegments(); + size_t decompressData(const byte_t* src, size_t src_len, byte_t* dst, size_t dst_capacity); void displayHeader(); void displayKernelCap(const nn::hac::KernelCapabilityControl& kern); + + std::string formatMappingAsString(const nn::hac::MemoryMappingHandler::sMemoryMapping& map) const; }; } \ No newline at end of file