mirror of
https://github.com/jakcron/nstool.git
synced 2024-12-22 18:55:29 +00:00
Merge pull request #57 from jakcron/kip-development
Implement Basic INI1/KIP1 Support.
This commit is contained in:
commit
077d0cc4ad
46
lib/libhac/include/nn/hac/IniHeader.h
Normal file
46
lib/libhac/include/nn/hac/IniHeader.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/List.h>
|
||||||
|
#include <fnd/IByteModel.h>
|
||||||
|
#include <nn/hac/define/ini.h>
|
||||||
|
|
||||||
|
namespace nn
|
||||||
|
{
|
||||||
|
namespace hac
|
||||||
|
{
|
||||||
|
class IniHeader :
|
||||||
|
public fnd::IByteModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IniHeader();
|
||||||
|
IniHeader(const IniHeader& other);
|
||||||
|
|
||||||
|
void operator=(const IniHeader& other);
|
||||||
|
bool operator==(const IniHeader& other) const;
|
||||||
|
bool operator!=(const IniHeader& other) const;
|
||||||
|
|
||||||
|
// IByteModel
|
||||||
|
void toBytes();
|
||||||
|
void fromBytes(const byte_t* data, size_t len);
|
||||||
|
const fnd::Vec<byte_t>& getBytes() const;
|
||||||
|
|
||||||
|
// variables
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
uint32_t getSize() const;
|
||||||
|
void setSize(uint32_t size);
|
||||||
|
|
||||||
|
uint32_t getKipNum() const;
|
||||||
|
void setKipNum(uint32_t num);
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "INI_HEADER";
|
||||||
|
|
||||||
|
// raw binary
|
||||||
|
fnd::Vec<byte_t> mRawBinary;
|
||||||
|
|
||||||
|
// variables
|
||||||
|
uint32_t mSize;
|
||||||
|
uint32_t mKipNum;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,6 +37,7 @@ namespace hac
|
||||||
inline kc::KernelCapId getCapId(uint32_t cap) const
|
inline kc::KernelCapId getCapId(uint32_t cap) const
|
||||||
{
|
{
|
||||||
kc::KernelCapId id = kc::KC_INVALID;
|
kc::KernelCapId id = kc::KC_INVALID;
|
||||||
|
|
||||||
for (byte_t tmp = 0; tmp < 31; tmp++)
|
for (byte_t tmp = 0; tmp < 31; tmp++)
|
||||||
{
|
{
|
||||||
if (((cap >> tmp) & 1) == 0)
|
if (((cap >> tmp) & 1) == 0)
|
||||||
|
@ -45,6 +46,10 @@ namespace hac
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (id == kc::KC_INVALID && cap == (uint32_t)0xffffffff)
|
||||||
|
id = kc::KC_STUB;
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
137
lib/libhac/include/nn/hac/KernelInitialProcessHeader.h
Normal file
137
lib/libhac/include/nn/hac/KernelInitialProcessHeader.h
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/List.h>
|
||||||
|
#include <fnd/IByteModel.h>
|
||||||
|
#include <nn/hac/define/kip.h>
|
||||||
|
#include <nn/hac/KernelCapabilityControl.h>
|
||||||
|
|
||||||
|
namespace nn
|
||||||
|
{
|
||||||
|
namespace hac
|
||||||
|
{
|
||||||
|
class KernelInitialProcessHeader :
|
||||||
|
public fnd::IByteModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct sLayout
|
||||||
|
{
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t size;
|
||||||
|
|
||||||
|
void operator=(const sLayout& other)
|
||||||
|
{
|
||||||
|
offset = other.offset;
|
||||||
|
size = other.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const sLayout& other) const
|
||||||
|
{
|
||||||
|
return (offset == other.offset) \
|
||||||
|
&& (size == other.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const sLayout& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sCodeSegment
|
||||||
|
{
|
||||||
|
sLayout file_layout;
|
||||||
|
sLayout memory_layout;
|
||||||
|
bool is_compressed;
|
||||||
|
|
||||||
|
void operator=(const sCodeSegment& other)
|
||||||
|
{
|
||||||
|
file_layout = other.file_layout;
|
||||||
|
memory_layout = other.memory_layout;
|
||||||
|
is_compressed = other.is_compressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const sCodeSegment& other) const
|
||||||
|
{
|
||||||
|
return (file_layout == other.file_layout) \
|
||||||
|
&& (memory_layout == other.memory_layout) \
|
||||||
|
&& (is_compressed == other.is_compressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const sCodeSegment& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
KernelInitialProcessHeader();
|
||||||
|
KernelInitialProcessHeader(const KernelInitialProcessHeader& other);
|
||||||
|
|
||||||
|
void operator=(const KernelInitialProcessHeader& other);
|
||||||
|
bool operator==(const KernelInitialProcessHeader& other) const;
|
||||||
|
bool operator!=(const KernelInitialProcessHeader& other) const;
|
||||||
|
|
||||||
|
// export/import binary
|
||||||
|
void toBytes();
|
||||||
|
void fromBytes(const byte_t* data, size_t len);
|
||||||
|
const fnd::Vec<byte_t>& getBytes() const;
|
||||||
|
|
||||||
|
// variables
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
const std::string& getName() const;
|
||||||
|
void setName(const std::string& name);
|
||||||
|
|
||||||
|
uint64_t getTitleId() const;
|
||||||
|
void setTitleId(uint64_t title_id);
|
||||||
|
|
||||||
|
kip::ProcessCategory getProcessCategory() const;
|
||||||
|
void setProcessCategory(kip::ProcessCategory cat);
|
||||||
|
|
||||||
|
const fnd::List<kip::HeaderFlags>& getFlagList() const;
|
||||||
|
void setFlagList(const fnd::List<kip::HeaderFlags>& flags);
|
||||||
|
|
||||||
|
byte_t getMainThreadPriority() const;
|
||||||
|
void setMainThreadPriority(byte_t priority);
|
||||||
|
|
||||||
|
byte_t getMainThreadCpuId() const;
|
||||||
|
void setMainThreadCpuId(byte_t cpu_id);
|
||||||
|
|
||||||
|
uint32_t getMainThreadStackSize() const;
|
||||||
|
void setMainThreadStackSize(uint32_t size);
|
||||||
|
|
||||||
|
const sCodeSegment& getTextSegmentInfo() const;
|
||||||
|
void setTextSegmentInfo(const sCodeSegment& info);
|
||||||
|
|
||||||
|
const sCodeSegment& getRoSegmentInfo() const;
|
||||||
|
void setRoSegmentInfo(const sCodeSegment& info);
|
||||||
|
|
||||||
|
const sCodeSegment& getDataSegmentInfo() const;
|
||||||
|
void setDataSegmentInfo(const sCodeSegment& info);
|
||||||
|
|
||||||
|
uint32_t getBssSize() const;
|
||||||
|
void setBssSize(uint32_t size);
|
||||||
|
|
||||||
|
const nn::hac::KernelCapabilityControl& getKernelCapabilities() const;
|
||||||
|
void setKernelCapabilities(const KernelCapabilityControl& kc);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "KERNEL_INITIAL_PROCESS_HEADER";
|
||||||
|
|
||||||
|
// raw binary
|
||||||
|
fnd::Vec<byte_t> mRawBinary;
|
||||||
|
|
||||||
|
// variables
|
||||||
|
std::string mName;
|
||||||
|
uint64_t mTitleId;
|
||||||
|
kip::ProcessCategory mProcessCategory;
|
||||||
|
fnd::List<kip::HeaderFlags> mFlagList;
|
||||||
|
byte_t mMainThreadPriority;
|
||||||
|
byte_t mMainThreadCpuId;
|
||||||
|
uint32_t mMainThreadStackSize;
|
||||||
|
sCodeSegment mTextInfo;
|
||||||
|
sCodeSegment mRoInfo;
|
||||||
|
sCodeSegment mDataInfo;
|
||||||
|
uint32_t mBssSize;
|
||||||
|
nn::hac::KernelCapabilityControl mKernelCapabilities;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
26
lib/libhac/include/nn/hac/define/ini.h
Normal file
26
lib/libhac/include/nn/hac/define/ini.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
#include <fnd/types.h>
|
||||||
|
#include <fnd/sha.h>
|
||||||
|
#include <nn/hac/define/macro.h>
|
||||||
|
|
||||||
|
namespace nn
|
||||||
|
{
|
||||||
|
namespace hac
|
||||||
|
{
|
||||||
|
namespace ini
|
||||||
|
{
|
||||||
|
static const uint32_t kIniStructMagic = _MAKE_STRUCT_MAGIC_U32("INI1");
|
||||||
|
static const size_t kMaxKipNum = 0x50;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma pack(push,1)
|
||||||
|
struct sIniHeader
|
||||||
|
{
|
||||||
|
le_uint32_t st_magic;
|
||||||
|
le_uint32_t size;
|
||||||
|
le_uint32_t kip_num;
|
||||||
|
byte_t reserved_01[0x4];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,8 @@ namespace hac
|
||||||
KC_MISC_PARAMS = 13,
|
KC_MISC_PARAMS = 13,
|
||||||
KC_KERNEL_VERSION = 14,
|
KC_KERNEL_VERSION = 14,
|
||||||
KC_HANDLE_TABLE_SIZE = 15,
|
KC_HANDLE_TABLE_SIZE = 15,
|
||||||
KC_MISC_FLAGS = 16
|
KC_MISC_FLAGS = 16,
|
||||||
|
KC_STUB = 32
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
65
lib/libhac/include/nn/hac/define/kip.h
Normal file
65
lib/libhac/include/nn/hac/define/kip.h
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#pragma once
|
||||||
|
#include <fnd/types.h>
|
||||||
|
#include <fnd/sha.h>
|
||||||
|
#include <nn/hac/define/macro.h>
|
||||||
|
|
||||||
|
namespace nn
|
||||||
|
{
|
||||||
|
namespace hac
|
||||||
|
{
|
||||||
|
namespace kip
|
||||||
|
{
|
||||||
|
static const uint32_t kKipStructMagic = _MAKE_STRUCT_MAGIC_U32("KIP1");
|
||||||
|
static const size_t kNameMaxLen = 0xC;
|
||||||
|
static const size_t kKernCapabilityNum = 0x20;
|
||||||
|
static const size_t kKernCapabilitySize = kKernCapabilityNum * sizeof(uint32_t);
|
||||||
|
|
||||||
|
enum ProcessCategory
|
||||||
|
{
|
||||||
|
PROCCAT_REGULAR,
|
||||||
|
PROCCAT_KERNAL_KIP
|
||||||
|
};
|
||||||
|
|
||||||
|
enum HeaderFlags
|
||||||
|
{
|
||||||
|
FLAG_TEXT_COMPRESS,
|
||||||
|
FLAG_RO_COMPRESS,
|
||||||
|
FLAG_DATA_COMPRESS,
|
||||||
|
FLAG_INSTRUCTION_64BIT,
|
||||||
|
FLAG_ADDR_SPACE_64BIT,
|
||||||
|
FLAG_USE_SYSTEM_POOL_PARTITION
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma pack(push,1)
|
||||||
|
struct sKipCodeSegment
|
||||||
|
{
|
||||||
|
le_uint32_t memory_offset;
|
||||||
|
le_uint32_t memory_size;
|
||||||
|
le_uint32_t file_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sKipHeader
|
||||||
|
{
|
||||||
|
le_uint32_t st_magic;
|
||||||
|
char name[kip::kNameMaxLen];
|
||||||
|
le_uint64_t title_id;
|
||||||
|
le_uint32_t process_category;
|
||||||
|
byte_t main_thread_priority;
|
||||||
|
byte_t main_thread_cpu_id;
|
||||||
|
byte_t reserved_01;
|
||||||
|
byte_t flags;
|
||||||
|
sKipCodeSegment text;
|
||||||
|
byte_t reserved_02[4];
|
||||||
|
sKipCodeSegment ro;
|
||||||
|
le_uint32_t main_thread_stack_size;
|
||||||
|
sKipCodeSegment data;
|
||||||
|
byte_t reserved_03[4];
|
||||||
|
sKipCodeSegment bss;
|
||||||
|
byte_t reserved_04[4];
|
||||||
|
byte_t reserved_05[0x20];
|
||||||
|
byte_t capabilities[kip::kKernCapabilitySize];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,7 +41,9 @@
|
||||||
<ClInclude Include="include\nn\hac\define\gc.h" />
|
<ClInclude Include="include\nn\hac\define\gc.h" />
|
||||||
<ClInclude Include="include\nn\hac\define\hierarchicalintegrity.h" />
|
<ClInclude Include="include\nn\hac\define\hierarchicalintegrity.h" />
|
||||||
<ClInclude Include="include\nn\hac\define\hierarchicalsha256.h" />
|
<ClInclude Include="include\nn\hac\define\hierarchicalsha256.h" />
|
||||||
|
<ClInclude Include="include\nn\hac\define\ini.h" />
|
||||||
<ClInclude Include="include\nn\hac\define\kc.h" />
|
<ClInclude Include="include\nn\hac\define\kc.h" />
|
||||||
|
<ClInclude Include="include\nn\hac\define\kip.h" />
|
||||||
<ClInclude Include="include\nn\hac\define\macro.h" />
|
<ClInclude Include="include\nn\hac\define\macro.h" />
|
||||||
<ClInclude Include="include\nn\hac\define\meta.h" />
|
<ClInclude Include="include\nn\hac\define\meta.h" />
|
||||||
<ClInclude Include="include\nn\hac\define\nacp.h" />
|
<ClInclude Include="include\nn\hac\define\nacp.h" />
|
||||||
|
@ -61,10 +63,12 @@
|
||||||
<ClInclude Include="include\nn\hac\HierarchicalSha256Header.h" />
|
<ClInclude Include="include\nn\hac\HierarchicalSha256Header.h" />
|
||||||
<ClInclude Include="include\nn\hac\IdConverter.h" />
|
<ClInclude Include="include\nn\hac\IdConverter.h" />
|
||||||
<ClInclude Include="include\nn\hac\IKernelCapabilityHandler.h" />
|
<ClInclude Include="include\nn\hac\IKernelCapabilityHandler.h" />
|
||||||
|
<ClInclude Include="include\nn\hac\IniHeader.h" />
|
||||||
<ClInclude Include="include\nn\hac\InteruptEntry.h" />
|
<ClInclude Include="include\nn\hac\InteruptEntry.h" />
|
||||||
<ClInclude Include="include\nn\hac\InteruptHandler.h" />
|
<ClInclude Include="include\nn\hac\InteruptHandler.h" />
|
||||||
<ClInclude Include="include\nn\hac\KernelCapabilityControl.h" />
|
<ClInclude Include="include\nn\hac\KernelCapabilityControl.h" />
|
||||||
<ClInclude Include="include\nn\hac\KernelCapabilityEntry.h" />
|
<ClInclude Include="include\nn\hac\KernelCapabilityEntry.h" />
|
||||||
|
<ClInclude Include="include\nn\hac\KernelInitialProcessHeader.h" />
|
||||||
<ClInclude Include="include\nn\hac\KernelVersionEntry.h" />
|
<ClInclude Include="include\nn\hac\KernelVersionEntry.h" />
|
||||||
<ClInclude Include="include\nn\hac\KernelVersionHandler.h" />
|
<ClInclude Include="include\nn\hac\KernelVersionHandler.h" />
|
||||||
<ClInclude Include="include\nn\hac\MemoryMappingHandler.h" />
|
<ClInclude Include="include\nn\hac\MemoryMappingHandler.h" />
|
||||||
|
@ -108,10 +112,12 @@
|
||||||
<ClCompile Include="source\HierarchicalIntegrityHeader.cpp" />
|
<ClCompile Include="source\HierarchicalIntegrityHeader.cpp" />
|
||||||
<ClCompile Include="source\HierarchicalSha256Header.cpp" />
|
<ClCompile Include="source\HierarchicalSha256Header.cpp" />
|
||||||
<ClCompile Include="source\IdConverter.cpp" />
|
<ClCompile Include="source\IdConverter.cpp" />
|
||||||
|
<ClCompile Include="source\IniHeader.cpp" />
|
||||||
<ClCompile Include="source\InteruptEntry.cpp" />
|
<ClCompile Include="source\InteruptEntry.cpp" />
|
||||||
<ClCompile Include="source\InteruptHandler.cpp" />
|
<ClCompile Include="source\InteruptHandler.cpp" />
|
||||||
<ClCompile Include="source\KernelCapabilityControl.cpp" />
|
<ClCompile Include="source\KernelCapabilityControl.cpp" />
|
||||||
<ClCompile Include="source\KernelCapabilityEntry.cpp" />
|
<ClCompile Include="source\KernelCapabilityEntry.cpp" />
|
||||||
|
<ClCompile Include="source\KernelInitialProcessHeader.cpp" />
|
||||||
<ClCompile Include="source\KernelVersionEntry.cpp" />
|
<ClCompile Include="source\KernelVersionEntry.cpp" />
|
||||||
<ClCompile Include="source\KernelVersionHandler.cpp" />
|
<ClCompile Include="source\KernelVersionHandler.cpp" />
|
||||||
<ClCompile Include="source\MemoryMappingHandler.cpp" />
|
<ClCompile Include="source\MemoryMappingHandler.cpp" />
|
||||||
|
|
|
@ -36,9 +36,15 @@
|
||||||
<ClInclude Include="include\nn\hac\define\hierarchicalsha256.h">
|
<ClInclude Include="include\nn\hac\define\hierarchicalsha256.h">
|
||||||
<Filter>Header Files\define</Filter>
|
<Filter>Header Files\define</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\nn\hac\define\ini.h">
|
||||||
|
<Filter>Header Files\define</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="include\nn\hac\define\kc.h">
|
<ClInclude Include="include\nn\hac\define\kc.h">
|
||||||
<Filter>Header Files\define</Filter>
|
<Filter>Header Files\define</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\nn\hac\define\kip.h">
|
||||||
|
<Filter>Header Files\define</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="include\nn\hac\define\macro.h">
|
<ClInclude Include="include\nn\hac\define\macro.h">
|
||||||
<Filter>Header Files\define</Filter>
|
<Filter>Header Files\define</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -132,6 +138,9 @@
|
||||||
<ClInclude Include="include\nn\hac\IKernelCapabilityHandler.h">
|
<ClInclude Include="include\nn\hac\IKernelCapabilityHandler.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\nn\hac\IniHeader.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="include\nn\hac\InteruptEntry.h">
|
<ClInclude Include="include\nn\hac\InteruptEntry.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -144,6 +153,9 @@
|
||||||
<ClInclude Include="include\nn\hac\KernelCapabilityEntry.h">
|
<ClInclude Include="include\nn\hac\KernelCapabilityEntry.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\nn\hac\KernelInitialProcessHeader.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="include\nn\hac\KernelVersionEntry.h">
|
<ClInclude Include="include\nn\hac\KernelVersionEntry.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -269,6 +281,9 @@
|
||||||
<ClCompile Include="source\IdConverter.cpp">
|
<ClCompile Include="source\IdConverter.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="source\IniHeader.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="source\InteruptEntry.cpp">
|
<ClCompile Include="source\InteruptEntry.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -281,6 +296,9 @@
|
||||||
<ClCompile Include="source\KernelCapabilityEntry.cpp">
|
<ClCompile Include="source\KernelCapabilityEntry.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="source\KernelInitialProcessHeader.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="source\KernelVersionEntry.cpp">
|
<ClCompile Include="source\KernelVersionEntry.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
114
lib/libhac/source/IniHeader.cpp
Normal file
114
lib/libhac/source/IniHeader.cpp
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
#include <nn/hac/IniHeader.h>
|
||||||
|
|
||||||
|
nn::hac::IniHeader::IniHeader()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
nn::hac::IniHeader::IniHeader(const IniHeader& other)
|
||||||
|
{
|
||||||
|
*this = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::IniHeader::operator=(const IniHeader& other)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
this->mSize = other.mSize;
|
||||||
|
this->mKipNum = other.mKipNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nn::hac::IniHeader::operator==(const IniHeader& other) const
|
||||||
|
{
|
||||||
|
return (this->mSize == other.mSize) \
|
||||||
|
&& (this->mKipNum == other.mKipNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nn::hac::IniHeader::operator!=(const IniHeader& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::IniHeader::toBytes()
|
||||||
|
{
|
||||||
|
mRawBinary.alloc(sizeof(sIniHeader));
|
||||||
|
nn::hac::sIniHeader* hdr = (nn::hac::sIniHeader*)mRawBinary.data();
|
||||||
|
|
||||||
|
// set header identifers
|
||||||
|
hdr->st_magic = ini::kIniStructMagic;
|
||||||
|
|
||||||
|
if (mKipNum > ini::kMaxKipNum)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Cannot generate INI Header (Too many KIPs)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// write variables
|
||||||
|
hdr->size = mSize;
|
||||||
|
hdr->kip_num = mKipNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::IniHeader::fromBytes(const byte_t* data, size_t len)
|
||||||
|
{
|
||||||
|
// check input data size
|
||||||
|
if (len < sizeof(sIniHeader))
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "INI header corrupt (header size is too small)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear internal members
|
||||||
|
clear();
|
||||||
|
|
||||||
|
// allocate internal local binary copy
|
||||||
|
mRawBinary.alloc(sizeof(sIniHeader));
|
||||||
|
memcpy(mRawBinary.data(), data, mRawBinary.size());
|
||||||
|
|
||||||
|
// get sIniHeader ptr
|
||||||
|
const nn::hac::sIniHeader* hdr = (const nn::hac::sIniHeader*)mRawBinary.data();
|
||||||
|
|
||||||
|
// check INI signature
|
||||||
|
if (hdr->st_magic.get() != ini::kIniStructMagic)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "INI header corrupt (unrecognised header signature)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check KIP num
|
||||||
|
if (hdr->kip_num.get() > ini::kMaxKipNum)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "INI header corrupt (too many KIPs)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// save variables
|
||||||
|
mSize = hdr->size.get();
|
||||||
|
mKipNum = hdr->kip_num.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
const fnd::Vec<byte_t>& nn::hac::IniHeader::getBytes() const
|
||||||
|
{
|
||||||
|
return mRawBinary;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::IniHeader::clear()
|
||||||
|
{
|
||||||
|
mRawBinary.clear();
|
||||||
|
mSize = 0;
|
||||||
|
mKipNum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nn::hac::IniHeader::getSize() const
|
||||||
|
{
|
||||||
|
return mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::IniHeader::setSize(uint32_t size)
|
||||||
|
{
|
||||||
|
mSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nn::hac::IniHeader::getKipNum() const
|
||||||
|
{
|
||||||
|
return mKipNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::IniHeader::setKipNum(uint32_t num)
|
||||||
|
{
|
||||||
|
mKipNum = num;
|
||||||
|
}
|
|
@ -26,12 +26,11 @@ void nn::hac::InteruptHandler::importKernelCapabilityList(const fnd::List<Kernel
|
||||||
{
|
{
|
||||||
if (caps.size() == 0)
|
if (caps.size() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// convert to interupts
|
// convert to interupts
|
||||||
fnd::List<InteruptEntry> interupts;
|
fnd::List<InteruptEntry> interupts;
|
||||||
for (size_t i = 0; i < caps.size(); i++)
|
for (size_t i = 0; i < caps.size(); i++)
|
||||||
{
|
{
|
||||||
interupts[i].setKernelCapability(caps[i]);
|
interupts.addElement(InteruptEntry(caps[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
mInterupts.clear();
|
mInterupts.clear();
|
||||||
|
|
|
@ -84,12 +84,12 @@ void nn::hac::KernelCapabilityControl::fromBytes(const byte_t * data, size_t len
|
||||||
fnd::List<KernelCapabilityEntry> handleTableSizeCaps;
|
fnd::List<KernelCapabilityEntry> handleTableSizeCaps;
|
||||||
fnd::List<KernelCapabilityEntry> miscFlagsCaps;
|
fnd::List<KernelCapabilityEntry> miscFlagsCaps;
|
||||||
|
|
||||||
const uint32_t* raw_caps = (const uint32_t*)mRawBinary.data();
|
const le_uint32_t* raw_caps = (const le_uint32_t*)mRawBinary.data();
|
||||||
size_t cap_num = mRawBinary.size() / sizeof(uint32_t);
|
size_t cap_num = mRawBinary.size() / sizeof(uint32_t);
|
||||||
KernelCapabilityEntry cap;
|
KernelCapabilityEntry cap;
|
||||||
for (size_t i = 0; i < cap_num; i++)
|
for (size_t i = 0; i < cap_num; i++)
|
||||||
{
|
{
|
||||||
cap.setCap(le_word(raw_caps[i]));
|
cap.setCap(raw_caps[i].get());
|
||||||
switch (cap.getType())
|
switch (cap.getType())
|
||||||
{
|
{
|
||||||
case (kc::KC_THREAD_INFO) :
|
case (kc::KC_THREAD_INFO) :
|
||||||
|
@ -117,6 +117,9 @@ void nn::hac::KernelCapabilityControl::fromBytes(const byte_t * data, size_t len
|
||||||
case (kc::KC_MISC_FLAGS):
|
case (kc::KC_MISC_FLAGS):
|
||||||
miscFlagsCaps.addElement(cap);
|
miscFlagsCaps.addElement(cap);
|
||||||
break;
|
break;
|
||||||
|
case (kc::KC_STUB):
|
||||||
|
// ignore stubbed
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw fnd::Exception(kModuleName, "Unsupported kernel capability type");
|
throw fnd::Exception(kModuleName, "Unsupported kernel capability type");
|
||||||
}
|
}
|
||||||
|
|
346
lib/libhac/source/KernelInitialProcessHeader.cpp
Normal file
346
lib/libhac/source/KernelInitialProcessHeader.cpp
Normal file
|
@ -0,0 +1,346 @@
|
||||||
|
#include <nn/hac/KernelInitialProcessHeader.h>
|
||||||
|
|
||||||
|
nn::hac::KernelInitialProcessHeader::KernelInitialProcessHeader()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
nn::hac::KernelInitialProcessHeader::KernelInitialProcessHeader(const KernelInitialProcessHeader& other)
|
||||||
|
{
|
||||||
|
*this = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::KernelInitialProcessHeader::operator=(const KernelInitialProcessHeader& other)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
this->mName = other.mName;
|
||||||
|
this->mTitleId = other.mTitleId;
|
||||||
|
this->mProcessCategory = other.mProcessCategory;
|
||||||
|
this->mFlagList = other.mFlagList;
|
||||||
|
this->mMainThreadPriority = other.mMainThreadPriority;
|
||||||
|
this->mMainThreadCpuId = other.mMainThreadCpuId;
|
||||||
|
this->mMainThreadStackSize = other.mMainThreadStackSize;
|
||||||
|
this->mTextInfo = other.mTextInfo;
|
||||||
|
this->mRoInfo = other.mRoInfo;
|
||||||
|
this->mDataInfo = other.mDataInfo;
|
||||||
|
this->mBssSize = other.mBssSize;
|
||||||
|
this->mKernelCapabilities = other.mKernelCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nn::hac::KernelInitialProcessHeader::operator==(const KernelInitialProcessHeader& other) const
|
||||||
|
{
|
||||||
|
return (this->mName == other.mName) \
|
||||||
|
&& (this->mTitleId == other.mTitleId) \
|
||||||
|
&& (this->mProcessCategory == other.mProcessCategory) \
|
||||||
|
&& (this->mFlagList == other.mFlagList) \
|
||||||
|
&& (this->mMainThreadPriority == other.mMainThreadPriority) \
|
||||||
|
&& (this->mMainThreadCpuId == other.mMainThreadCpuId) \
|
||||||
|
&& (this->mMainThreadStackSize == other.mMainThreadStackSize) \
|
||||||
|
&& (this->mTextInfo == other.mTextInfo) \
|
||||||
|
&& (this->mRoInfo == other.mRoInfo) \
|
||||||
|
&& (this->mDataInfo == other.mDataInfo) \
|
||||||
|
&& (this->mBssSize == other.mBssSize) \
|
||||||
|
&& (this->mKernelCapabilities == other.mKernelCapabilities);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nn::hac::KernelInitialProcessHeader::operator!=(const KernelInitialProcessHeader& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::KernelInitialProcessHeader::toBytes()
|
||||||
|
{
|
||||||
|
mRawBinary.alloc(sizeof(sKipHeader));
|
||||||
|
nn::hac::sKipHeader* hdr = (nn::hac::sKipHeader*)mRawBinary.data();
|
||||||
|
|
||||||
|
// set header identifers
|
||||||
|
hdr->st_magic = kip::kKipStructMagic;
|
||||||
|
|
||||||
|
// variable to store flags before commiting to header
|
||||||
|
byte_t flags = 0;
|
||||||
|
|
||||||
|
// properties
|
||||||
|
strncpy(hdr->name, mName.c_str(), kip::kNameMaxLen);
|
||||||
|
hdr->title_id = mTitleId;
|
||||||
|
hdr->process_category = mProcessCategory;
|
||||||
|
hdr->main_thread_priority = mMainThreadPriority;
|
||||||
|
hdr->main_thread_cpu_id = mMainThreadCpuId;
|
||||||
|
hdr->main_thread_stack_size = mMainThreadStackSize;
|
||||||
|
|
||||||
|
// kernel caps
|
||||||
|
mKernelCapabilities.toBytes();
|
||||||
|
if (mKernelCapabilities.getBytes().size() > kip::kKernCapabilitySize)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Too many kernel capabilities");
|
||||||
|
}
|
||||||
|
memcpy(hdr->capabilities, mKernelCapabilities.getBytes().data(), mKernelCapabilities.getBytes().size());
|
||||||
|
|
||||||
|
// stub remaining entries
|
||||||
|
if (mKernelCapabilities.getBytes().size() < kip::kKernCapabilitySize)
|
||||||
|
{
|
||||||
|
memset(hdr->capabilities + mKernelCapabilities.getBytes().size(), 0xff, kip::kKernCapabilitySize - mKernelCapabilities.getBytes().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// flags
|
||||||
|
for (size_t i = 0; i < mFlagList.size(); i++)
|
||||||
|
{
|
||||||
|
switch(mFlagList[i])
|
||||||
|
{
|
||||||
|
case (kip::FLAG_TEXT_COMPRESS) :
|
||||||
|
case (kip::FLAG_RO_COMPRESS) :
|
||||||
|
case (kip::FLAG_DATA_COMPRESS) :
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
flags |= _BIT(mFlagList[i] & 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set bss size
|
||||||
|
hdr->bss.file_size = 0;
|
||||||
|
hdr->bss.memory_offset = 0;
|
||||||
|
hdr->bss.memory_size = mBssSize;
|
||||||
|
|
||||||
|
// set text segment
|
||||||
|
hdr->text.memory_offset = mTextInfo.memory_layout.offset;
|
||||||
|
hdr->text.memory_size = mTextInfo.memory_layout.size;
|
||||||
|
hdr->text.file_size = mTextInfo.file_layout.size;
|
||||||
|
if (mTextInfo.is_compressed)
|
||||||
|
{
|
||||||
|
flags |= _BIT(kip::FLAG_TEXT_COMPRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set ro segment
|
||||||
|
hdr->ro.memory_offset = mRoInfo.memory_layout.offset;
|
||||||
|
hdr->ro.memory_size = mRoInfo.memory_layout.size;
|
||||||
|
hdr->ro.file_size = mRoInfo.file_layout.size;
|
||||||
|
if (mRoInfo.is_compressed)
|
||||||
|
{
|
||||||
|
flags |= _BIT(kip::FLAG_TEXT_COMPRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set data segment
|
||||||
|
hdr->data.memory_offset = mDataInfo.memory_layout.offset;
|
||||||
|
hdr->data.memory_size = mDataInfo.memory_layout.size;
|
||||||
|
hdr->data.file_size = mDataInfo.file_layout.size;
|
||||||
|
if (mDataInfo.is_compressed)
|
||||||
|
{
|
||||||
|
flags |= _BIT(kip::FLAG_TEXT_COMPRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
hdr->flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::KernelInitialProcessHeader::fromBytes(const byte_t* data, size_t len)
|
||||||
|
{
|
||||||
|
// check input data size
|
||||||
|
if (len < sizeof(sKipHeader))
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "KIP header size is too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear internal members
|
||||||
|
clear();
|
||||||
|
|
||||||
|
// allocate internal local binary copy
|
||||||
|
mRawBinary.alloc(sizeof(sKipHeader));
|
||||||
|
memcpy(mRawBinary.data(), data, mRawBinary.size());
|
||||||
|
|
||||||
|
// get sKipHeader ptr
|
||||||
|
const nn::hac::sKipHeader* hdr = (const nn::hac::sKipHeader*)mRawBinary.data();
|
||||||
|
|
||||||
|
// check KIP signature
|
||||||
|
if (hdr->st_magic.get() != kip::kKipStructMagic)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "KIP header corrupt (unrecognised header signature)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// properties
|
||||||
|
if (hdr->name[0] != 0)
|
||||||
|
mName = std::string(hdr->name, _MIN(strlen(hdr->name), kip::kNameMaxLen));
|
||||||
|
mTitleId = hdr->title_id.get();
|
||||||
|
mProcessCategory = (kip::ProcessCategory)hdr->process_category.get();
|
||||||
|
mMainThreadPriority = hdr->main_thread_priority;
|
||||||
|
mMainThreadCpuId = hdr->main_thread_cpu_id;
|
||||||
|
mMainThreadStackSize = hdr->main_thread_stack_size.get();
|
||||||
|
mKernelCapabilities.fromBytes(hdr->capabilities, kip::kKernCapabilitySize);
|
||||||
|
|
||||||
|
for (byte_t i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
if (_HAS_BIT(hdr->flags, i))
|
||||||
|
{
|
||||||
|
switch(i)
|
||||||
|
{
|
||||||
|
case (kip::FLAG_TEXT_COMPRESS) :
|
||||||
|
case (kip::FLAG_RO_COMPRESS) :
|
||||||
|
case (kip::FLAG_DATA_COMPRESS) :
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mFlagList.addElement((kip::HeaderFlags)i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// code segment info
|
||||||
|
mTextInfo.file_layout.offset = sizeof(sKipHeader);
|
||||||
|
mTextInfo.file_layout.size = hdr->text.file_size.get();
|
||||||
|
mTextInfo.memory_layout.offset = hdr->text.memory_offset.get();
|
||||||
|
mTextInfo.memory_layout.size = hdr->text.memory_size.get();
|
||||||
|
mTextInfo.is_compressed = _HAS_BIT(hdr->flags, kip::FLAG_TEXT_COMPRESS);
|
||||||
|
|
||||||
|
mRoInfo.file_layout.offset = mTextInfo.file_layout.offset + mTextInfo.file_layout.size;
|
||||||
|
mRoInfo.file_layout.size = hdr->ro.file_size.get();
|
||||||
|
mRoInfo.memory_layout.offset = hdr->ro.memory_offset.get();
|
||||||
|
mRoInfo.memory_layout.size = hdr->ro.memory_size.get();
|
||||||
|
mRoInfo.is_compressed = _HAS_BIT(hdr->flags, kip::FLAG_RO_COMPRESS);
|
||||||
|
|
||||||
|
mDataInfo.file_layout.offset = mRoInfo.file_layout.offset + mRoInfo.file_layout.size;
|
||||||
|
mDataInfo.file_layout.size = hdr->data.file_size.get();
|
||||||
|
mDataInfo.memory_layout.offset = hdr->data.memory_offset.get();
|
||||||
|
mDataInfo.memory_layout.size = hdr->data.memory_size.get();
|
||||||
|
mDataInfo.is_compressed = _HAS_BIT(hdr->flags, kip::FLAG_DATA_COMPRESS);
|
||||||
|
|
||||||
|
mBssSize = hdr->bss.memory_size.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
const fnd::Vec<byte_t>& nn::hac::KernelInitialProcessHeader::getBytes() const
|
||||||
|
{
|
||||||
|
return mRawBinary;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::KernelInitialProcessHeader::clear()
|
||||||
|
{
|
||||||
|
mRawBinary.clear();
|
||||||
|
mName.clear();
|
||||||
|
mTitleId = 0;
|
||||||
|
mProcessCategory = (kip::ProcessCategory)0;
|
||||||
|
mFlagList.clear();
|
||||||
|
mMainThreadPriority = 0;
|
||||||
|
mMainThreadCpuId = 0;
|
||||||
|
mMainThreadStackSize = 0;
|
||||||
|
mTextInfo = sCodeSegment();
|
||||||
|
mRoInfo = sCodeSegment();
|
||||||
|
mDataInfo = sCodeSegment();
|
||||||
|
mBssSize = 0;
|
||||||
|
mKernelCapabilities.clear();;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& nn::hac::KernelInitialProcessHeader::getName() const
|
||||||
|
{
|
||||||
|
return mName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::KernelInitialProcessHeader::setName(const std::string& name)
|
||||||
|
{
|
||||||
|
mName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t nn::hac::KernelInitialProcessHeader::getTitleId() const
|
||||||
|
{
|
||||||
|
return mTitleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::KernelInitialProcessHeader::setTitleId(uint64_t title_id)
|
||||||
|
{
|
||||||
|
mTitleId = title_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn::hac::kip::ProcessCategory nn::hac::KernelInitialProcessHeader::getProcessCategory() const
|
||||||
|
{
|
||||||
|
return mProcessCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::KernelInitialProcessHeader::setProcessCategory(kip::ProcessCategory cat)
|
||||||
|
{
|
||||||
|
mProcessCategory = cat;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fnd::List<nn::hac::kip::HeaderFlags>& nn::hac::KernelInitialProcessHeader::getFlagList() const
|
||||||
|
{
|
||||||
|
return mFlagList;
|
||||||
|
}
|
||||||
|
void nn::hac::KernelInitialProcessHeader::setFlagList(const fnd::List<kip::HeaderFlags>& flags)
|
||||||
|
{
|
||||||
|
mFlagList = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_t nn::hac::KernelInitialProcessHeader::getMainThreadPriority() const
|
||||||
|
{
|
||||||
|
return mMainThreadPriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::KernelInitialProcessHeader::setMainThreadPriority(byte_t priority)
|
||||||
|
{
|
||||||
|
mMainThreadPriority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_t nn::hac::KernelInitialProcessHeader::getMainThreadCpuId() const
|
||||||
|
{
|
||||||
|
return mMainThreadCpuId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::KernelInitialProcessHeader::setMainThreadCpuId(byte_t cpu_id)
|
||||||
|
{
|
||||||
|
mMainThreadCpuId = cpu_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nn::hac::KernelInitialProcessHeader::getMainThreadStackSize() const
|
||||||
|
{
|
||||||
|
return mMainThreadStackSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::KernelInitialProcessHeader::setMainThreadStackSize(uint32_t size)
|
||||||
|
{
|
||||||
|
mMainThreadStackSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nn::hac::KernelInitialProcessHeader::sCodeSegment& nn::hac::KernelInitialProcessHeader::getTextSegmentInfo() const
|
||||||
|
{
|
||||||
|
return mTextInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::KernelInitialProcessHeader::setTextSegmentInfo(const sCodeSegment& info)
|
||||||
|
{
|
||||||
|
mTextInfo = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nn::hac::KernelInitialProcessHeader::sCodeSegment& nn::hac::KernelInitialProcessHeader::getRoSegmentInfo() const
|
||||||
|
{
|
||||||
|
return mRoInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::KernelInitialProcessHeader::setRoSegmentInfo(const sCodeSegment& info)
|
||||||
|
{
|
||||||
|
mRoInfo = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nn::hac::KernelInitialProcessHeader::sCodeSegment& nn::hac::KernelInitialProcessHeader::getDataSegmentInfo() const
|
||||||
|
{
|
||||||
|
return mDataInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::KernelInitialProcessHeader::setDataSegmentInfo(const sCodeSegment& info)
|
||||||
|
{
|
||||||
|
mDataInfo = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nn::hac::KernelInitialProcessHeader::getBssSize() const
|
||||||
|
{
|
||||||
|
return mBssSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::KernelInitialProcessHeader::setBssSize(uint32_t size)
|
||||||
|
{
|
||||||
|
mBssSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nn::hac::KernelCapabilityControl& nn::hac::KernelInitialProcessHeader::getKernelCapabilities() const
|
||||||
|
{
|
||||||
|
return mKernelCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::hac::KernelInitialProcessHeader::setKernelCapabilities(const KernelCapabilityControl& kc)
|
||||||
|
{
|
||||||
|
mKernelCapabilities = kc;
|
||||||
|
}
|
|
@ -10,6 +10,8 @@ General purpose reading/extraction tool for Nintendo Switch file formats.
|
||||||
* Content Metadata (.cnmt)
|
* Content Metadata (.cnmt)
|
||||||
* Nintendo Software Object (.nso)
|
* Nintendo Software Object (.nso)
|
||||||
* Nintendo Relocatable Software Object (.nro)
|
* Nintendo Relocatable Software Object (.nro)
|
||||||
|
* Kernel Initial Process List (.ini)
|
||||||
|
* Kernel Initial Process (.kip)
|
||||||
* Nintendo Application Control Property (.nacp)
|
* Nintendo Application Control Property (.nacp)
|
||||||
* ES Ticket (v2 only) (.tik)
|
* ES Ticket (v2 only) (.tik)
|
||||||
* PKI Certificate (.cert)
|
* PKI Certificate (.cert)
|
||||||
|
@ -21,7 +23,7 @@ Usage: nstool [options... ] <file>
|
||||||
General Options:
|
General Options:
|
||||||
-d, --dev Use devkit keyset.
|
-d, --dev Use devkit keyset.
|
||||||
-k, --keyset Specify keyset file.
|
-k, --keyset Specify keyset file.
|
||||||
-t, --type Specify input file type. [xci, pfs, romfs, nca, meta, cnmt, nso, nro, nacp, aset, cert, tik]
|
-t, --type Specify input file type. [xci, pfs, romfs, nca, meta, cnmt, nso, nro, ini, kip, nacp, aset, cert, tik]
|
||||||
-y, --verify Verify file.
|
-y, --verify Verify file.
|
||||||
|
|
||||||
Output Options:
|
Output Options:
|
||||||
|
@ -60,6 +62,10 @@ Usage: nstool [options... ] <file>
|
||||||
--listsym Print Code Symbols.
|
--listsym Print Code Symbols.
|
||||||
--insttype Specify instruction type [64bit|32bit] (64bit is assumed).
|
--insttype Specify instruction type [64bit|32bit] (64bit is assumed).
|
||||||
|
|
||||||
|
INI (Initial Process List Blob)
|
||||||
|
nstool [--kipdir <dir>] <file>
|
||||||
|
--kipdir Extract embedded KIPs to directory.
|
||||||
|
|
||||||
ASET (Homebrew Asset Blob)
|
ASET (Homebrew Asset Blob)
|
||||||
nstool [--listfs] [--icon <file> --nacp <file> --fsdir <dir>] <file>
|
nstool [--listfs] [--icon <file> --nacp <file> --fsdir <dir>] <file>
|
||||||
--listfs Print filesystem in embedded RomFS partition.
|
--listfs Print filesystem in embedded RomFS partition.
|
||||||
|
|
|
@ -183,7 +183,10 @@
|
||||||
<ClInclude Include="source\common.h" />
|
<ClInclude Include="source\common.h" />
|
||||||
<ClInclude Include="source\ElfSymbolParser.h" />
|
<ClInclude Include="source\ElfSymbolParser.h" />
|
||||||
<ClInclude Include="source\EsTikProcess.h" />
|
<ClInclude Include="source\EsTikProcess.h" />
|
||||||
|
<ClInclude Include="source\GameCardProcess.h" />
|
||||||
|
<ClInclude Include="source\IniProcess.h" />
|
||||||
<ClInclude Include="source\KeyConfiguration.h" />
|
<ClInclude Include="source\KeyConfiguration.h" />
|
||||||
|
<ClInclude Include="source\KipProcess.h" />
|
||||||
<ClInclude Include="source\MetaProcess.h" />
|
<ClInclude Include="source\MetaProcess.h" />
|
||||||
<ClInclude Include="source\NacpProcess.h" />
|
<ClInclude Include="source\NacpProcess.h" />
|
||||||
<ClInclude Include="source\NcaProcess.h" />
|
<ClInclude Include="source\NcaProcess.h" />
|
||||||
|
@ -197,14 +200,16 @@
|
||||||
<ClInclude Include="source\SdkApiString.h" />
|
<ClInclude Include="source\SdkApiString.h" />
|
||||||
<ClInclude Include="source\UserSettings.h" />
|
<ClInclude Include="source\UserSettings.h" />
|
||||||
<ClInclude Include="source\version.h" />
|
<ClInclude Include="source\version.h" />
|
||||||
<ClInclude Include="source\GameCardProcess.h" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="source\AssetProcess.cpp" />
|
<ClCompile Include="source\AssetProcess.cpp" />
|
||||||
<ClCompile Include="source\CnmtProcess.cpp" />
|
<ClCompile Include="source\CnmtProcess.cpp" />
|
||||||
<ClCompile Include="source\ElfSymbolParser.cpp" />
|
<ClCompile Include="source\ElfSymbolParser.cpp" />
|
||||||
<ClCompile Include="source\EsTikProcess.cpp" />
|
<ClCompile Include="source\EsTikProcess.cpp" />
|
||||||
|
<ClCompile Include="source\GameCardProcess.cpp" />
|
||||||
|
<ClCompile Include="source\IniProcess.cpp" />
|
||||||
<ClCompile Include="source\KeyConfiguration.cpp" />
|
<ClCompile Include="source\KeyConfiguration.cpp" />
|
||||||
|
<ClCompile Include="source\KipProcess.cpp" />
|
||||||
<ClCompile Include="source\main.cpp" />
|
<ClCompile Include="source\main.cpp" />
|
||||||
<ClCompile Include="source\MetaProcess.cpp" />
|
<ClCompile Include="source\MetaProcess.cpp" />
|
||||||
<ClCompile Include="source\NacpProcess.cpp" />
|
<ClCompile Include="source\NacpProcess.cpp" />
|
||||||
|
@ -218,7 +223,6 @@
|
||||||
<ClCompile Include="source\RomfsProcess.cpp" />
|
<ClCompile Include="source\RomfsProcess.cpp" />
|
||||||
<ClCompile Include="source\SdkApiString.cpp" />
|
<ClCompile Include="source\SdkApiString.cpp" />
|
||||||
<ClCompile Include="source\UserSettings.cpp" />
|
<ClCompile Include="source\UserSettings.cpp" />
|
||||||
<ClCompile Include="source\GameCardProcess.cpp" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|
|
@ -34,9 +34,18 @@
|
||||||
<ClInclude Include="source\EsTikProcess.h">
|
<ClInclude Include="source\EsTikProcess.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="source\GameCardProcess.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="source\IniProcess.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="source\KeyConfiguration.h">
|
<ClInclude Include="source\KeyConfiguration.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="source\KipProcess.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="source\MetaProcess.h">
|
<ClInclude Include="source\MetaProcess.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -76,9 +85,6 @@
|
||||||
<ClInclude Include="source\version.h">
|
<ClInclude Include="source\version.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="source\GameCardProcess.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="source\AssetProcess.cpp">
|
<ClCompile Include="source\AssetProcess.cpp">
|
||||||
|
@ -93,9 +99,18 @@
|
||||||
<ClCompile Include="source\EsTikProcess.cpp">
|
<ClCompile Include="source\EsTikProcess.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="source\GameCardProcess.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="source\IniProcess.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="source\KeyConfiguration.cpp">
|
<ClCompile Include="source\KeyConfiguration.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="source\KipProcess.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="source\main.cpp">
|
<ClCompile Include="source\main.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -135,8 +150,5 @@
|
||||||
<ClCompile Include="source\UserSettings.cpp">
|
<ClCompile Include="source\UserSettings.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="source\GameCardProcess.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
170
programs/nstool/source/IniProcess.cpp
Normal file
170
programs/nstool/source/IniProcess.cpp
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <fnd/io.h>
|
||||||
|
#include <fnd/SimpleFile.h>
|
||||||
|
#include <fnd/SimpleTextOutput.h>
|
||||||
|
#include <fnd/OffsetAdjustedIFile.h>
|
||||||
|
#include <fnd/Vec.h>
|
||||||
|
#include "IniProcess.h"
|
||||||
|
#include "KipProcess.h"
|
||||||
|
|
||||||
|
|
||||||
|
IniProcess::IniProcess() :
|
||||||
|
mFile(),
|
||||||
|
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||||
|
mVerify(false),
|
||||||
|
mDoExtractKip(false),
|
||||||
|
mKipExtractPath()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void IniProcess::process()
|
||||||
|
{
|
||||||
|
importHeader();
|
||||||
|
importKipList();
|
||||||
|
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||||
|
{
|
||||||
|
displayHeader();
|
||||||
|
displayKipList();
|
||||||
|
}
|
||||||
|
if (mDoExtractKip)
|
||||||
|
{
|
||||||
|
extractKipList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IniProcess::setInputFile(const fnd::SharedPtr<fnd::IFile>& file)
|
||||||
|
{
|
||||||
|
mFile = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IniProcess::setCliOutputMode(CliOutputMode type)
|
||||||
|
{
|
||||||
|
mCliOutputMode = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IniProcess::setVerifyMode(bool verify)
|
||||||
|
{
|
||||||
|
mVerify = verify;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IniProcess::setKipExtractPath(const std::string& path)
|
||||||
|
{
|
||||||
|
mDoExtractKip = true;
|
||||||
|
mKipExtractPath = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IniProcess::importHeader()
|
||||||
|
{
|
||||||
|
fnd::Vec<byte_t> scratch;
|
||||||
|
|
||||||
|
if (*mFile == nullptr)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "No file reader set.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*mFile)->size() < sizeof(nn::hac::sIniHeader))
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Corrupt INI: file too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch.alloc(sizeof(nn::hac::sIniHeader));
|
||||||
|
(*mFile)->read(scratch.data(), 0, scratch.size());
|
||||||
|
|
||||||
|
mHdr.fromBytes(scratch.data(), scratch.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IniProcess::importKipList()
|
||||||
|
{
|
||||||
|
// kip pos info
|
||||||
|
size_t kip_pos = sizeof(nn::hac::sIniHeader);
|
||||||
|
size_t kip_size = 0;
|
||||||
|
|
||||||
|
// tmp data to determine size
|
||||||
|
fnd::Vec<byte_t> hdr_raw;
|
||||||
|
nn::hac::KernelInitialProcessHeader hdr;
|
||||||
|
|
||||||
|
hdr_raw.alloc(sizeof(nn::hac::sKipHeader));
|
||||||
|
for (size_t i = 0; i < mHdr.getKipNum(); i++)
|
||||||
|
{
|
||||||
|
(*mFile)->read(hdr_raw.data(), kip_pos, hdr_raw.size());
|
||||||
|
hdr.fromBytes(hdr_raw.data(), hdr_raw.size());
|
||||||
|
kip_size = getKipSizeFromHeader(hdr);
|
||||||
|
mKipList.addElement(new fnd::OffsetAdjustedIFile(mFile, kip_pos, kip_size));
|
||||||
|
kip_pos += kip_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IniProcess::displayHeader()
|
||||||
|
{
|
||||||
|
std::cout << "[INI Header]" << std::endl;
|
||||||
|
std::cout << " Size: 0x" << std::hex << mHdr.getSize() << std::endl;
|
||||||
|
std::cout << " KIP Num: " << std::dec << (uint32_t)mHdr.getKipNum() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IniProcess::displayKipList()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < mKipList.size(); i++)
|
||||||
|
{
|
||||||
|
KipProcess obj;
|
||||||
|
|
||||||
|
obj.setInputFile(mKipList[i]);
|
||||||
|
obj.setCliOutputMode(mCliOutputMode);
|
||||||
|
obj.setVerifyMode(mVerify);
|
||||||
|
|
||||||
|
obj.process();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IniProcess::extractKipList()
|
||||||
|
{
|
||||||
|
fnd::Vec<byte_t> cache;
|
||||||
|
nn::hac::KernelInitialProcessHeader hdr;
|
||||||
|
|
||||||
|
|
||||||
|
// allocate cache memory
|
||||||
|
cache.alloc(kCacheSize);
|
||||||
|
|
||||||
|
// make extract dir
|
||||||
|
fnd::io::makeDirectory(mKipExtractPath);
|
||||||
|
|
||||||
|
|
||||||
|
// outfile object for writing KIP
|
||||||
|
fnd::SimpleFile out_file;
|
||||||
|
std::string out_path;
|
||||||
|
size_t out_size;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mKipList.size(); i++)
|
||||||
|
{
|
||||||
|
// read header
|
||||||
|
(*mKipList[i])->read(cache.data(), 0, cache.size());
|
||||||
|
hdr.fromBytes(cache.data(), cache.size());
|
||||||
|
|
||||||
|
// generate path
|
||||||
|
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 (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||||
|
printf("extract=[%s]\n", out_path.c_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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t 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;
|
||||||
|
}
|
47
programs/nstool/source/IniProcess.h
Normal file
47
programs/nstool/source/IniProcess.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/types.h>
|
||||||
|
#include <fnd/IFile.h>
|
||||||
|
#include <fnd/List.h>
|
||||||
|
#include <fnd/SharedPtr.h>
|
||||||
|
#include <nn/hac/IniHeader.h>
|
||||||
|
#include <nn/hac/KernelInitialProcessHeader.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
class IniProcess
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IniProcess();
|
||||||
|
|
||||||
|
void process();
|
||||||
|
|
||||||
|
void setInputFile(const fnd::SharedPtr<fnd::IFile>& file);
|
||||||
|
void setCliOutputMode(CliOutputMode type);
|
||||||
|
void setVerifyMode(bool verify);
|
||||||
|
|
||||||
|
void setKipExtractPath(const std::string& path);
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "IniProcess";
|
||||||
|
const std::string kKipExtention = ".kip";
|
||||||
|
const size_t kCacheSize = 0x10000;
|
||||||
|
|
||||||
|
fnd::SharedPtr<fnd::IFile> mFile;
|
||||||
|
CliOutputMode mCliOutputMode;
|
||||||
|
bool mVerify;
|
||||||
|
|
||||||
|
bool mDoExtractKip;
|
||||||
|
std::string mKipExtractPath;
|
||||||
|
|
||||||
|
nn::hac::IniHeader mHdr;
|
||||||
|
fnd::List<fnd::SharedPtr<fnd::IFile>> mKipList;
|
||||||
|
|
||||||
|
void importHeader();
|
||||||
|
void importKipList();
|
||||||
|
void displayHeader();
|
||||||
|
void displayKipList();
|
||||||
|
void extractKipList();
|
||||||
|
|
||||||
|
size_t getKipSizeFromHeader(const nn::hac::KernelInitialProcessHeader& hdr) const;
|
||||||
|
};
|
767
programs/nstool/source/KipProcess.cpp
Normal file
767
programs/nstool/source/KipProcess.cpp
Normal file
|
@ -0,0 +1,767 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <fnd/SimpleTextOutput.h>
|
||||||
|
#include <fnd/OffsetAdjustedIFile.h>
|
||||||
|
#include <fnd/Vec.h>
|
||||||
|
#include "KipProcess.h"
|
||||||
|
|
||||||
|
KipProcess::KipProcess():
|
||||||
|
mFile(),
|
||||||
|
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||||
|
mVerify(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void KipProcess::process()
|
||||||
|
{
|
||||||
|
importHeader();
|
||||||
|
//importCodeSegments();
|
||||||
|
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||||
|
{
|
||||||
|
displayHeader();
|
||||||
|
displayKernelCap(mHdr.getKernelCapabilities());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KipProcess::setInputFile(const fnd::SharedPtr<fnd::IFile>& file)
|
||||||
|
{
|
||||||
|
mFile = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KipProcess::setCliOutputMode(CliOutputMode type)
|
||||||
|
{
|
||||||
|
mCliOutputMode = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KipProcess::setVerifyMode(bool verify)
|
||||||
|
{
|
||||||
|
mVerify = verify;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KipProcess::importHeader()
|
||||||
|
{
|
||||||
|
fnd::Vec<byte_t> scratch;
|
||||||
|
|
||||||
|
if (*mFile == nullptr)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "No file reader set.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*mFile)->size() < sizeof(nn::hac::sKipHeader))
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Corrupt KIP: file too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch.alloc(sizeof(nn::hac::sKipHeader));
|
||||||
|
(*mFile)->read(scratch.data(), 0, scratch.size());
|
||||||
|
|
||||||
|
mHdr.fromBytes(scratch.data(), scratch.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void KipProcess::importCodeSegments()
|
||||||
|
{
|
||||||
|
#ifdef _KIP_COMPRESSION_IMPLEMENTED
|
||||||
|
fnd::Vec<byte_t> 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())
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "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());
|
||||||
|
}
|
||||||
|
#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())
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "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());
|
||||||
|
}
|
||||||
|
#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
|
||||||
|
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())
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "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());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
mDataBlob.alloc(mHdr.getDataSegmentInfo().file_layout.size);
|
||||||
|
(*mFile)->read(mDataBlob.data(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.size());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void 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 << " ProcessCategory: " << getProcessCategoryStr(mHdr.getProcessCategory()) << std::endl;
|
||||||
|
std::cout << " InstructionType: " << getInstructionTypeStr(mHdr.getFlagList().hasElement(nn::hac::kip::FLAG_INSTRUCTION_64BIT)) << std::endl;
|
||||||
|
std::cout << " AddrSpaceWidth: " << getAddressSpaceStr(mHdr.getFlagList().hasElement(nn::hac::kip::FLAG_ADDR_SPACE_64BIT)) << std::endl;
|
||||||
|
std::cout << " MemoryPool: " << getMemoryPoolStr(mHdr.getFlagList().hasElement(nn::hac::kip::FLAG_USE_SYSTEM_POOL_PARTITION)) << std::endl;
|
||||||
|
std::cout << " Program Sections:" << std::endl;
|
||||||
|
std::cout << " .text:" << std::endl;
|
||||||
|
if (_HAS_BIT(mCliOutputMode, OUTPUT_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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
if (_HAS_BIT(mCliOutputMode, OUTPUT_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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
if (_HAS_BIT(mCliOutputMode, OUTPUT_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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
|
||||||
|
{
|
||||||
|
std::cout << "[Kernel Capabilities]" << std::endl;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kern.getSystemCalls().isSet())
|
||||||
|
{
|
||||||
|
fnd::List<uint8_t> syscalls = kern.getSystemCalls().getSystemCalls();
|
||||||
|
std::cout << " SystemCalls:" << std::endl;
|
||||||
|
std::cout << " ";
|
||||||
|
size_t lineLen = 0;
|
||||||
|
for (size_t i = 0; i < syscalls.size(); i++)
|
||||||
|
{
|
||||||
|
if (lineLen > 60)
|
||||||
|
{
|
||||||
|
lineLen = 0;
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << " ";
|
||||||
|
}
|
||||||
|
std::cout << getSystemCallStr(syscalls[i]);
|
||||||
|
if (syscalls[i] != syscalls.atBack())
|
||||||
|
std::cout << ", ";
|
||||||
|
lineLen += strlen(getSystemCallStr(syscalls[i]));
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
if (kern.getMemoryMaps().isSet())
|
||||||
|
{
|
||||||
|
fnd::List<nn::hac::MemoryMappingHandler::sMemoryMapping> maps = kern.getMemoryMaps().getMemoryMaps();
|
||||||
|
fnd::List<nn::hac::MemoryMappingHandler::sMemoryMapping> ioMaps = kern.getMemoryMaps().getIoMemoryMaps();
|
||||||
|
|
||||||
|
std::cout << " MemoryMaps:" << std::endl;
|
||||||
|
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=" << getMemMapPermStr(maps[i].perm) << ") (type=" << getMemMapTypeStr(maps[i].type) << ")" << std::endl;
|
||||||
|
}
|
||||||
|
//std::cout << " IoMaps:" << std::endl;
|
||||||
|
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=" << getMemMapPermStr(ioMaps[i].perm) << ") (type=" << getMemMapTypeStr(ioMaps[i].type) << ")" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (kern.getInterupts().isSet())
|
||||||
|
{
|
||||||
|
fnd::List<uint16_t> interupts = kern.getInterupts().getInteruptList();
|
||||||
|
std::cout << " Interupts Flags:" << std::endl;
|
||||||
|
for (uint32_t i = 0; i < interupts.size(); i++)
|
||||||
|
{
|
||||||
|
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 << ", ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
if (kern.getMiscParams().isSet())
|
||||||
|
{
|
||||||
|
std::cout << " ProgramType: " << std::dec << (uint32_t)kern.getMiscParams().getProgramType() << std::endl;
|
||||||
|
}
|
||||||
|
if (kern.getKernelVersion().isSet())
|
||||||
|
{
|
||||||
|
std::cout << " Kernel Version: " << std::dec << (uint32_t)kern.getKernelVersion().getVerMajor() << "." << (uint32_t)kern.getKernelVersion().getVerMinor() << std::endl;
|
||||||
|
}
|
||||||
|
if (kern.getHandleTableSize().isSet())
|
||||||
|
{
|
||||||
|
std::cout << " Handle Table Size: 0x" << std::hex << kern.getHandleTableSize().getHandleTableSize() << std::endl;
|
||||||
|
}
|
||||||
|
if (kern.getMiscFlags().isSet())
|
||||||
|
{
|
||||||
|
fnd::List<nn::hac::MiscFlagsHandler::Flags> flagList = kern.getMiscFlags().getFlagList();
|
||||||
|
|
||||||
|
std::cout << " Misc Flags:" << std::endl;
|
||||||
|
for (uint32_t i = 0; i < flagList.size(); i++)
|
||||||
|
{
|
||||||
|
if (i % 10 == 0)
|
||||||
|
{
|
||||||
|
if (i != 0)
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << " ";
|
||||||
|
}
|
||||||
|
std::cout << getMiscFlagStr(flagList[i]);
|
||||||
|
if (flagList[i] != flagList.atBack())
|
||||||
|
std::cout << ", ";
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* KipProcess::getProcessCategoryStr(nn::hac::kip::ProcessCategory var) const
|
||||||
|
{
|
||||||
|
const char* str = nullptr;
|
||||||
|
|
||||||
|
switch(var)
|
||||||
|
{
|
||||||
|
case (nn::hac::kip::PROCCAT_REGULAR):
|
||||||
|
str = "NormalProcess";
|
||||||
|
break;
|
||||||
|
case (nn::hac::kip::PROCCAT_KERNAL_KIP):
|
||||||
|
str = "KernelInitalProcess";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str = "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* KipProcess::getInstructionTypeStr(bool is64Bit) const
|
||||||
|
{
|
||||||
|
return is64Bit? "64Bit" : "32Bit";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* KipProcess::getAddressSpaceStr(bool is64Bit) const
|
||||||
|
{
|
||||||
|
return is64Bit? "64Bit" : "32Bit";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* KipProcess::getMemoryPoolStr(bool isSystemPool) const
|
||||||
|
{
|
||||||
|
return isSystemPool? "System" : "Application";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* KipProcess::getMiscFlagStr(nn::hac::MiscFlagsHandler::Flags flag) const
|
||||||
|
{
|
||||||
|
const char* str = nullptr;
|
||||||
|
|
||||||
|
switch(flag)
|
||||||
|
{
|
||||||
|
case (nn::hac::MiscFlagsHandler::FLAG_ENABLE_DEBUG):
|
||||||
|
str = "EnableDebug";
|
||||||
|
break;
|
||||||
|
case (nn::hac::MiscFlagsHandler::FLAG_FORCE_DEBUG):
|
||||||
|
str = "ForceDebug";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str = "Unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* KipProcess::getSystemCallStr(byte_t syscall_id) const
|
||||||
|
{
|
||||||
|
const char* str = nullptr;
|
||||||
|
|
||||||
|
switch(syscall_id)
|
||||||
|
{
|
||||||
|
case (0x01):
|
||||||
|
str = "SetHeapSize";
|
||||||
|
break;
|
||||||
|
case (0x02):
|
||||||
|
str = "SetMemoryPermission";
|
||||||
|
break;
|
||||||
|
case (0x03):
|
||||||
|
str = "SetMemoryAttribute";
|
||||||
|
break;
|
||||||
|
case (0x04):
|
||||||
|
str = "MapMemory";
|
||||||
|
break;
|
||||||
|
case (0x05):
|
||||||
|
str = "UnmapMemory";
|
||||||
|
break;
|
||||||
|
case (0x06):
|
||||||
|
str = "QueryMemory";
|
||||||
|
break;
|
||||||
|
case (0x07):
|
||||||
|
str = "ExitProcess";
|
||||||
|
break;
|
||||||
|
case (0x08):
|
||||||
|
str = "CreateThread";
|
||||||
|
break;
|
||||||
|
case (0x09):
|
||||||
|
str = "StartThread";
|
||||||
|
break;
|
||||||
|
case (0x0a):
|
||||||
|
str = "ExitThread";
|
||||||
|
break;
|
||||||
|
case (0x0b):
|
||||||
|
str = "SleepThread";
|
||||||
|
break;
|
||||||
|
case (0x0c):
|
||||||
|
str = "GetThreadPriority";
|
||||||
|
break;
|
||||||
|
case (0x0d):
|
||||||
|
str = "SetThreadPriority";
|
||||||
|
break;
|
||||||
|
case (0x0e):
|
||||||
|
str = "GetThreadCoreMask";
|
||||||
|
break;
|
||||||
|
case (0x0f):
|
||||||
|
str = "SetThreadCoreMask";
|
||||||
|
break;
|
||||||
|
case (0x10):
|
||||||
|
str = "GetCurrentProcessorNumber";
|
||||||
|
break;
|
||||||
|
case (0x11):
|
||||||
|
str = "SignalEvent";
|
||||||
|
break;
|
||||||
|
case (0x12):
|
||||||
|
str = "ClearEvent";
|
||||||
|
break;
|
||||||
|
case (0x13):
|
||||||
|
str = "MapSharedMemory";
|
||||||
|
break;
|
||||||
|
case (0x14):
|
||||||
|
str = "UnmapSharedMemory";
|
||||||
|
break;
|
||||||
|
case (0x15):
|
||||||
|
str = "CreateTransferMemory";
|
||||||
|
break;
|
||||||
|
case (0x16):
|
||||||
|
str = "CloseHandle";
|
||||||
|
break;
|
||||||
|
case (0x17):
|
||||||
|
str = "ResetSignal";
|
||||||
|
break;
|
||||||
|
case (0x18):
|
||||||
|
str = "WaitSynchronization";
|
||||||
|
break;
|
||||||
|
case (0x19):
|
||||||
|
str = "CancelSynchronization";
|
||||||
|
break;
|
||||||
|
case (0x1a):
|
||||||
|
str = "ArbitrateLock";
|
||||||
|
break;
|
||||||
|
case (0x1b):
|
||||||
|
str = "ArbitrateUnlock";
|
||||||
|
break;
|
||||||
|
case (0x1c):
|
||||||
|
str = "WaitProcessWideKeyAtomic";
|
||||||
|
break;
|
||||||
|
case (0x1d):
|
||||||
|
str = "SignalProcessWideKey";
|
||||||
|
break;
|
||||||
|
case (0x1e):
|
||||||
|
str = "GetSystemTick";
|
||||||
|
break;
|
||||||
|
case (0x1f):
|
||||||
|
str = "ConnectToNamedPort";
|
||||||
|
break;
|
||||||
|
case (0x20):
|
||||||
|
str = "SendSyncRequestLight";
|
||||||
|
break;
|
||||||
|
case (0x21):
|
||||||
|
str = "SendSyncRequest";
|
||||||
|
break;
|
||||||
|
case (0x22):
|
||||||
|
str = "SendSyncRequestWithUserBuffer";
|
||||||
|
break;
|
||||||
|
case (0x23):
|
||||||
|
str = "SendAsyncRequestWithUserBuffer";
|
||||||
|
break;
|
||||||
|
case (0x24):
|
||||||
|
str = "GetProcessId";
|
||||||
|
break;
|
||||||
|
case (0x25):
|
||||||
|
str = "GetThreadId";
|
||||||
|
break;
|
||||||
|
case (0x26):
|
||||||
|
str = "Break";
|
||||||
|
break;
|
||||||
|
case (0x27):
|
||||||
|
str = "OutputDebugString";
|
||||||
|
break;
|
||||||
|
case (0x28):
|
||||||
|
str = "ReturnFromException";
|
||||||
|
break;
|
||||||
|
case (0x29):
|
||||||
|
str = "GetInfo";
|
||||||
|
break;
|
||||||
|
case (0x2a):
|
||||||
|
str = "FlushEntireDataCache";
|
||||||
|
break;
|
||||||
|
case (0x2b):
|
||||||
|
str = "FlushDataCache";
|
||||||
|
break;
|
||||||
|
case (0x2c):
|
||||||
|
str = "MapPhysicalMemory";
|
||||||
|
break;
|
||||||
|
case (0x2d):
|
||||||
|
str = "UnmapPhysicalMemory";
|
||||||
|
break;
|
||||||
|
case (0x2e):
|
||||||
|
str = "GetFutureThreadInfo";
|
||||||
|
break;
|
||||||
|
case (0x2f):
|
||||||
|
str = "GetLastThreadInfo";
|
||||||
|
break;
|
||||||
|
case (0x30):
|
||||||
|
str = "GetResourceLimitLimitValue";
|
||||||
|
break;
|
||||||
|
case (0x31):
|
||||||
|
str = "GetResourceLimitCurrentValue";
|
||||||
|
break;
|
||||||
|
case (0x32):
|
||||||
|
str = "SetThreadActivity";
|
||||||
|
break;
|
||||||
|
case (0x33):
|
||||||
|
str = "GetThreadContext3";
|
||||||
|
break;
|
||||||
|
case (0x34):
|
||||||
|
str = "WaitForAddress";
|
||||||
|
break;
|
||||||
|
case (0x35):
|
||||||
|
str = "SignalToAddress";
|
||||||
|
break;
|
||||||
|
case (0x36):
|
||||||
|
str = "svc36";
|
||||||
|
break;
|
||||||
|
case (0x37):
|
||||||
|
str = "svc37";
|
||||||
|
break;
|
||||||
|
case (0x38):
|
||||||
|
str = "svc38";
|
||||||
|
break;
|
||||||
|
case (0x39):
|
||||||
|
str = "svc39";
|
||||||
|
break;
|
||||||
|
case (0x3a):
|
||||||
|
str = "svc3A";
|
||||||
|
break;
|
||||||
|
case (0x3b):
|
||||||
|
str = "svc3B";
|
||||||
|
break;
|
||||||
|
case (0x3c):
|
||||||
|
str = "DumpInfo";
|
||||||
|
break;
|
||||||
|
case (0x3d):
|
||||||
|
str = "DumpInfoNew";
|
||||||
|
break;
|
||||||
|
case (0x3e):
|
||||||
|
str = "svc3E";
|
||||||
|
break;
|
||||||
|
case (0x3f):
|
||||||
|
str = "svc3F";
|
||||||
|
break;
|
||||||
|
case (0x40):
|
||||||
|
str = "CreateSession";
|
||||||
|
break;
|
||||||
|
case (0x41):
|
||||||
|
str = "AcceptSession";
|
||||||
|
break;
|
||||||
|
case (0x42):
|
||||||
|
str = "ReplyAndReceiveLight";
|
||||||
|
break;
|
||||||
|
case (0x43):
|
||||||
|
str = "ReplyAndReceive";
|
||||||
|
break;
|
||||||
|
case (0x44):
|
||||||
|
str = "ReplyAndReceiveWithUserBuffer";
|
||||||
|
break;
|
||||||
|
case (0x45):
|
||||||
|
str = "CreateEvent";
|
||||||
|
break;
|
||||||
|
case (0x46):
|
||||||
|
str = "svc46";
|
||||||
|
break;
|
||||||
|
case (0x47):
|
||||||
|
str = "svc47";
|
||||||
|
break;
|
||||||
|
case (0x48):
|
||||||
|
str = "MapPhysicalMemoryUnsafe";
|
||||||
|
break;
|
||||||
|
case (0x49):
|
||||||
|
str = "UnmapPhysicalMemoryUnsafe";
|
||||||
|
break;
|
||||||
|
case (0x4a):
|
||||||
|
str = "SetUnsafeLimit";
|
||||||
|
break;
|
||||||
|
case (0x4b):
|
||||||
|
str = "CreateCodeMemory";
|
||||||
|
break;
|
||||||
|
case (0x4c):
|
||||||
|
str = "ControlCodeMemory";
|
||||||
|
break;
|
||||||
|
case (0x4d):
|
||||||
|
str = "SleepSystem";
|
||||||
|
break;
|
||||||
|
case (0x4e):
|
||||||
|
str = "ReadWriteRegister";
|
||||||
|
break;
|
||||||
|
case (0x4f):
|
||||||
|
str = "SetProcessActivity";
|
||||||
|
break;
|
||||||
|
case (0x50):
|
||||||
|
str = "CreateSharedMemory";
|
||||||
|
break;
|
||||||
|
case (0x51):
|
||||||
|
str = "MapTransferMemory";
|
||||||
|
break;
|
||||||
|
case (0x52):
|
||||||
|
str = "UnmapTransferMemory";
|
||||||
|
break;
|
||||||
|
case (0x53):
|
||||||
|
str = "CreateInterruptEvent";
|
||||||
|
break;
|
||||||
|
case (0x54):
|
||||||
|
str = "QueryPhysicalAddress";
|
||||||
|
break;
|
||||||
|
case (0x55):
|
||||||
|
str = "QueryIoMapping";
|
||||||
|
break;
|
||||||
|
case (0x56):
|
||||||
|
str = "CreateDeviceAddressSpace";
|
||||||
|
break;
|
||||||
|
case (0x57):
|
||||||
|
str = "AttachDeviceAddressSpace";
|
||||||
|
break;
|
||||||
|
case (0x58):
|
||||||
|
str = "DetachDeviceAddressSpace";
|
||||||
|
break;
|
||||||
|
case (0x59):
|
||||||
|
str = "MapDeviceAddressSpaceByForce";
|
||||||
|
break;
|
||||||
|
case (0x5a):
|
||||||
|
str = "MapDeviceAddressSpaceAligned";
|
||||||
|
break;
|
||||||
|
case (0x5b):
|
||||||
|
str = "MapDeviceAddressSpace";
|
||||||
|
break;
|
||||||
|
case (0x5c):
|
||||||
|
str = "UnmapDeviceAddressSpace";
|
||||||
|
break;
|
||||||
|
case (0x5d):
|
||||||
|
str = "InvalidateProcessDataCache";
|
||||||
|
break;
|
||||||
|
case (0x5e):
|
||||||
|
str = "StoreProcessDataCache";
|
||||||
|
break;
|
||||||
|
case (0x5f):
|
||||||
|
str = "FlushProcessDataCache";
|
||||||
|
break;
|
||||||
|
case (0x60):
|
||||||
|
str = "DebugActiveProcess";
|
||||||
|
break;
|
||||||
|
case (0x61):
|
||||||
|
str = "BreakDebugProcess";
|
||||||
|
break;
|
||||||
|
case (0x62):
|
||||||
|
str = "TerminateDebugProcess";
|
||||||
|
break;
|
||||||
|
case (0x63):
|
||||||
|
str = "GetDebugEvent";
|
||||||
|
break;
|
||||||
|
case (0x64):
|
||||||
|
str = "ContinueDebugEvent";
|
||||||
|
break;
|
||||||
|
case (0x65):
|
||||||
|
str = "GetProcessList";
|
||||||
|
break;
|
||||||
|
case (0x66):
|
||||||
|
str = "GetThreadList";
|
||||||
|
break;
|
||||||
|
case (0x67):
|
||||||
|
str = "GetDebugThreadContext";
|
||||||
|
break;
|
||||||
|
case (0x68):
|
||||||
|
str = "SetDebugThreadContext";
|
||||||
|
break;
|
||||||
|
case (0x69):
|
||||||
|
str = "QueryDebugProcessMemory";
|
||||||
|
break;
|
||||||
|
case (0x6a):
|
||||||
|
str = "ReadDebugProcessMemory";
|
||||||
|
break;
|
||||||
|
case (0x6b):
|
||||||
|
str = "WriteDebugProcessMemory";
|
||||||
|
break;
|
||||||
|
case (0x6c):
|
||||||
|
str = "SetHardwareBreakPoint";
|
||||||
|
break;
|
||||||
|
case (0x6d):
|
||||||
|
str = "GetDebugThreadParam";
|
||||||
|
break;
|
||||||
|
case (0x6e):
|
||||||
|
str = "svc6E";
|
||||||
|
break;
|
||||||
|
case (0x6f):
|
||||||
|
str = "GetSystemInfo";
|
||||||
|
break;
|
||||||
|
case (0x70):
|
||||||
|
str = "CreatePort";
|
||||||
|
break;
|
||||||
|
case (0x71):
|
||||||
|
str = "ManageNamedPort";
|
||||||
|
break;
|
||||||
|
case (0x72):
|
||||||
|
str = "ConnectToPort";
|
||||||
|
break;
|
||||||
|
case (0x73):
|
||||||
|
str = "SetProcessMemoryPermission";
|
||||||
|
break;
|
||||||
|
case (0x74):
|
||||||
|
str = "MapProcessMemory";
|
||||||
|
break;
|
||||||
|
case (0x75):
|
||||||
|
str = "UnmapProcessMemory";
|
||||||
|
break;
|
||||||
|
case (0x76):
|
||||||
|
str = "QueryProcessMemory";
|
||||||
|
break;
|
||||||
|
case (0x77):
|
||||||
|
str = "MapProcessCodeMemory";
|
||||||
|
break;
|
||||||
|
case (0x78):
|
||||||
|
str = "UnmapProcessCodeMemory";
|
||||||
|
break;
|
||||||
|
case (0x79):
|
||||||
|
str = "CreateProcess";
|
||||||
|
break;
|
||||||
|
case (0x7a):
|
||||||
|
str = "StartProcess";
|
||||||
|
break;
|
||||||
|
case (0x7b):
|
||||||
|
str = "TerminateProcess";
|
||||||
|
break;
|
||||||
|
case (0x7c):
|
||||||
|
str = "GetProcessInfo";
|
||||||
|
break;
|
||||||
|
case (0x7d):
|
||||||
|
str = "CreateResourceLimit";
|
||||||
|
break;
|
||||||
|
case (0x7e):
|
||||||
|
str = "SetResourceLimitLimitValue";
|
||||||
|
break;
|
||||||
|
case (0x7f):
|
||||||
|
str = "CallSecureMonitor";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str = "Unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* KipProcess::getMemMapPermStr(nn::hac::MemoryMappingHandler::MemoryPerm type) const
|
||||||
|
{
|
||||||
|
const char* str = nullptr;
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case (nn::hac::MemoryMappingHandler::MEM_RW):
|
||||||
|
str = "RW";
|
||||||
|
break;
|
||||||
|
case (nn::hac::MemoryMappingHandler::MEM_RO):
|
||||||
|
str = "RO";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str = "Unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* KipProcess::getMemMapTypeStr(nn::hac::MemoryMappingHandler::MappingType type) const
|
||||||
|
{
|
||||||
|
const char* str = nullptr;
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case (nn::hac::MemoryMappingHandler::MAP_IO):
|
||||||
|
str = "Io";
|
||||||
|
break;
|
||||||
|
case (nn::hac::MemoryMappingHandler::MAP_STATIC):
|
||||||
|
str = "Static";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str = "Unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
44
programs/nstool/source/KipProcess.h
Normal file
44
programs/nstool/source/KipProcess.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/types.h>
|
||||||
|
#include <fnd/IFile.h>
|
||||||
|
#include <fnd/SharedPtr.h>
|
||||||
|
#include <nn/hac/KernelInitialProcessHeader.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
class KipProcess
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KipProcess();
|
||||||
|
|
||||||
|
void process();
|
||||||
|
|
||||||
|
void setInputFile(const fnd::SharedPtr<fnd::IFile>& file);
|
||||||
|
void setCliOutputMode(CliOutputMode type);
|
||||||
|
void setVerifyMode(bool verify);
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "KipProcess";
|
||||||
|
|
||||||
|
fnd::SharedPtr<fnd::IFile> mFile;
|
||||||
|
CliOutputMode mCliOutputMode;
|
||||||
|
bool mVerify;
|
||||||
|
|
||||||
|
nn::hac::KernelInitialProcessHeader mHdr;
|
||||||
|
fnd::Vec<byte_t> mTextBlob, mRoBlob, mDataBlob;
|
||||||
|
|
||||||
|
void importHeader();
|
||||||
|
void importCodeSegments();
|
||||||
|
void displayHeader();
|
||||||
|
void displayKernelCap(const nn::hac::KernelCapabilityControl& kern);
|
||||||
|
|
||||||
|
const char* getProcessCategoryStr(nn::hac::kip::ProcessCategory var) const;
|
||||||
|
const char* getInstructionTypeStr(bool is64Bit) const;
|
||||||
|
const char* getAddressSpaceStr(bool is64Bit) const;
|
||||||
|
const char* getMemoryPoolStr(bool isSystemPool) const;
|
||||||
|
const char* getMiscFlagStr(nn::hac::MiscFlagsHandler::Flags flag) const;
|
||||||
|
const char* getSystemCallStr(byte_t syscall_id) const;
|
||||||
|
const char* getMemMapPermStr(nn::hac::MemoryMappingHandler::MemoryPerm type) const;
|
||||||
|
const char* getMemMapTypeStr(nn::hac::MemoryMappingHandler::MappingType type) const;
|
||||||
|
};
|
|
@ -24,6 +24,8 @@
|
||||||
#include <nn/hac/define/nacp.h>
|
#include <nn/hac/define/nacp.h>
|
||||||
#include <nn/hac/define/nso.h>
|
#include <nn/hac/define/nso.h>
|
||||||
#include <nn/hac/define/nro.h>
|
#include <nn/hac/define/nro.h>
|
||||||
|
#include <nn/hac/define/ini.h>
|
||||||
|
#include <nn/hac/define/kip.h>
|
||||||
#include <nn/hac/define/aset.h>
|
#include <nn/hac/define/aset.h>
|
||||||
#include <nn/pki/SignedData.h>
|
#include <nn/pki/SignedData.h>
|
||||||
#include <nn/pki/CertificateBody.h>
|
#include <nn/pki/CertificateBody.h>
|
||||||
|
@ -52,7 +54,7 @@ void UserSettings::showHelp()
|
||||||
printf("\n General Options:\n");
|
printf("\n General Options:\n");
|
||||||
printf(" -d, --dev Use devkit keyset.\n");
|
printf(" -d, --dev Use devkit keyset.\n");
|
||||||
printf(" -k, --keyset Specify keyset file.\n");
|
printf(" -k, --keyset Specify keyset file.\n");
|
||||||
printf(" -t, --type Specify input file type. [xci, pfs, romfs, nca, meta, cnmt, nso, nro, nacp, aset, cert, tik]\n");
|
printf(" -t, --type Specify input file type. [xci, pfs, romfs, nca, meta, cnmt, nso, nro, ini, kip, nacp, aset, cert, tik]\n");
|
||||||
printf(" -y, --verify Verify file.\n");
|
printf(" -y, --verify Verify file.\n");
|
||||||
printf("\n Output Options:\n");
|
printf("\n Output Options:\n");
|
||||||
printf(" --showkeys Show keys generated.\n");
|
printf(" --showkeys Show keys generated.\n");
|
||||||
|
@ -85,6 +87,9 @@ void UserSettings::showHelp()
|
||||||
printf(" --listapi Print SDK API List.\n");
|
printf(" --listapi Print SDK API List.\n");
|
||||||
printf(" --listsym Print Code Symbols.\n");
|
printf(" --listsym Print Code Symbols.\n");
|
||||||
printf(" --insttype Specify instruction type [64bit|32bit] (64bit is assumed).\n");
|
printf(" --insttype Specify instruction type [64bit|32bit] (64bit is assumed).\n");
|
||||||
|
printf("\n INI (Initial Process List Blob)\n");
|
||||||
|
printf(" %s [--kipdir <dir>] <file>\n", BIN_NAME);
|
||||||
|
printf(" --kipdir Extract embedded KIPs to directory.\n");
|
||||||
printf("\n ASET (Homebrew Asset Blob)\n");
|
printf("\n ASET (Homebrew Asset Blob)\n");
|
||||||
printf(" %s [--listfs] [--icon <file> --nacp <file> --fsdir <dir>] <file>\n", BIN_NAME);
|
printf(" %s [--listfs] [--icon <file> --nacp <file> --fsdir <dir>] <file>\n", BIN_NAME);
|
||||||
printf(" --listfs Print filesystem in embedded RomFS partition.\n");
|
printf(" --listfs Print filesystem in embedded RomFS partition.\n");
|
||||||
|
@ -183,6 +188,11 @@ const sOptional<std::string>& UserSettings::getNcaPart3Path() const
|
||||||
return mNcaPart3Path;
|
return mNcaPart3Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sOptional<std::string>& UserSettings::getKipExtractPath() const
|
||||||
|
{
|
||||||
|
return mKipExtractPath;
|
||||||
|
}
|
||||||
|
|
||||||
const sOptional<std::string>& UserSettings::getAssetIconPath() const
|
const sOptional<std::string>& UserSettings::getAssetIconPath() const
|
||||||
{
|
{
|
||||||
return mAssetIconPath;
|
return mAssetIconPath;
|
||||||
|
@ -366,6 +376,12 @@ void UserSettings::populateCmdArgs(const std::vector<std::string>& arg_list, sCm
|
||||||
cmd_args.inst_type = arg_list[i + 1];
|
cmd_args.inst_type = arg_list[i + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (arg_list[i] == "--kipdir")
|
||||||
|
{
|
||||||
|
if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter.");
|
||||||
|
cmd_args.kip_extract_path = arg_list[i + 1];
|
||||||
|
}
|
||||||
|
|
||||||
else if (arg_list[i] == "--icon")
|
else if (arg_list[i] == "--icon")
|
||||||
{
|
{
|
||||||
if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter.");
|
if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter.");
|
||||||
|
@ -544,6 +560,8 @@ void UserSettings::populateUserSettings(sCmdArgs& args)
|
||||||
mNcaPart2Path = args.part2_path;
|
mNcaPart2Path = args.part2_path;
|
||||||
mNcaPart3Path = args.part3_path;
|
mNcaPart3Path = args.part3_path;
|
||||||
|
|
||||||
|
mKipExtractPath = args.kip_extract_path;
|
||||||
|
|
||||||
// determine the architecture type for NSO/NRO
|
// determine the architecture type for NSO/NRO
|
||||||
if (args.inst_type.isSet)
|
if (args.inst_type.isSet)
|
||||||
mInstructionType = getInstructionTypeFromString(*args.inst_type);
|
mInstructionType = getInstructionTypeFromString(*args.inst_type);
|
||||||
|
@ -610,6 +628,10 @@ FileType UserSettings::getFileTypeFromString(const std::string& type_str)
|
||||||
type = FILE_NSO;
|
type = FILE_NSO;
|
||||||
else if (str == "nro")
|
else if (str == "nro")
|
||||||
type = FILE_NRO;
|
type = FILE_NRO;
|
||||||
|
else if (str == "ini")
|
||||||
|
type = FILE_INI;
|
||||||
|
else if (str == "kip")
|
||||||
|
type = FILE_KIP;
|
||||||
else if (str == "nacp")
|
else if (str == "nacp")
|
||||||
type = FILE_NACP;
|
type = FILE_NACP;
|
||||||
else if (str == "cert")
|
else if (str == "cert")
|
||||||
|
@ -665,9 +687,15 @@ FileType UserSettings::determineFileTypeFromFile(const std::string& path)
|
||||||
// test nso
|
// test nso
|
||||||
else if (_ASSERT_SIZE(sizeof(nn::hac::sNsoHeader)) && _TYPE_PTR(nn::hac::sNsoHeader)->st_magic.get() == nn::hac::nso::kNsoStructMagic)
|
else if (_ASSERT_SIZE(sizeof(nn::hac::sNsoHeader)) && _TYPE_PTR(nn::hac::sNsoHeader)->st_magic.get() == nn::hac::nso::kNsoStructMagic)
|
||||||
file_type = FILE_NSO;
|
file_type = FILE_NSO;
|
||||||
// test nso
|
// test nro
|
||||||
else if (_ASSERT_SIZE(sizeof(nn::hac::sNroHeader)) && _TYPE_PTR(nn::hac::sNroHeader)->st_magic.get() == nn::hac::nro::kNroStructMagic)
|
else if (_ASSERT_SIZE(sizeof(nn::hac::sNroHeader)) && _TYPE_PTR(nn::hac::sNroHeader)->st_magic.get() == nn::hac::nro::kNroStructMagic)
|
||||||
file_type = FILE_NRO;
|
file_type = FILE_NRO;
|
||||||
|
// test ini
|
||||||
|
else if (_ASSERT_SIZE(sizeof(nn::hac::sIniHeader)) && _TYPE_PTR(nn::hac::sIniHeader)->st_magic.get() == nn::hac::ini::kIniStructMagic)
|
||||||
|
file_type = FILE_INI;
|
||||||
|
// test kip
|
||||||
|
else if (_ASSERT_SIZE(sizeof(nn::hac::sKipHeader)) && _TYPE_PTR(nn::hac::sKipHeader)->st_magic.get() == nn::hac::kip::kKipStructMagic)
|
||||||
|
file_type = FILE_KIP;
|
||||||
// test pki certificate
|
// test pki certificate
|
||||||
else if (determineValidEsCertFromSample(scratch))
|
else if (determineValidEsCertFromSample(scratch))
|
||||||
file_type = FILE_PKI_CERT;
|
file_type = FILE_PKI_CERT;
|
||||||
|
|
|
@ -41,6 +41,7 @@ public:
|
||||||
const sOptional<std::string>& getNcaPart1Path() const;
|
const sOptional<std::string>& getNcaPart1Path() const;
|
||||||
const sOptional<std::string>& getNcaPart2Path() const;
|
const sOptional<std::string>& getNcaPart2Path() const;
|
||||||
const sOptional<std::string>& getNcaPart3Path() const;
|
const sOptional<std::string>& getNcaPart3Path() const;
|
||||||
|
const sOptional<std::string>& getKipExtractPath() const;
|
||||||
const sOptional<std::string>& getAssetIconPath() const;
|
const sOptional<std::string>& getAssetIconPath() const;
|
||||||
const sOptional<std::string>& getAssetNacpPath() const;
|
const sOptional<std::string>& getAssetNacpPath() const;
|
||||||
const fnd::List<nn::pki::SignedData<nn::pki::CertificateBody>>& getCertificateChain() const;
|
const fnd::List<nn::pki::SignedData<nn::pki::CertificateBody>>& getCertificateChain() const;
|
||||||
|
@ -78,6 +79,7 @@ private:
|
||||||
sOptional<std::string> part1_path;
|
sOptional<std::string> part1_path;
|
||||||
sOptional<std::string> part2_path;
|
sOptional<std::string> part2_path;
|
||||||
sOptional<std::string> part3_path;
|
sOptional<std::string> part3_path;
|
||||||
|
sOptional<std::string> kip_extract_path;
|
||||||
sOptional<bool> list_api;
|
sOptional<bool> list_api;
|
||||||
sOptional<bool> list_sym;
|
sOptional<bool> list_sym;
|
||||||
sOptional<std::string> inst_type;
|
sOptional<std::string> inst_type;
|
||||||
|
@ -103,6 +105,8 @@ private:
|
||||||
sOptional<std::string> mNcaPart2Path;
|
sOptional<std::string> mNcaPart2Path;
|
||||||
sOptional<std::string> mNcaPart3Path;
|
sOptional<std::string> mNcaPart3Path;
|
||||||
|
|
||||||
|
sOptional<std::string> mKipExtractPath;
|
||||||
|
|
||||||
sOptional<std::string> mAssetIconPath;
|
sOptional<std::string> mAssetIconPath;
|
||||||
sOptional<std::string> mAssetNacpPath;
|
sOptional<std::string> mAssetNacpPath;
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@ enum FileType
|
||||||
FILE_NSO,
|
FILE_NSO,
|
||||||
FILE_NRO,
|
FILE_NRO,
|
||||||
FILE_NACP,
|
FILE_NACP,
|
||||||
|
FILE_INI,
|
||||||
|
FILE_KIP,
|
||||||
FILE_PKI_CERT,
|
FILE_PKI_CERT,
|
||||||
FILE_ES_TIK,
|
FILE_ES_TIK,
|
||||||
FILE_HB_ASSET,
|
FILE_HB_ASSET,
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include "NsoProcess.h"
|
#include "NsoProcess.h"
|
||||||
#include "NroProcess.h"
|
#include "NroProcess.h"
|
||||||
#include "NacpProcess.h"
|
#include "NacpProcess.h"
|
||||||
|
#include "IniProcess.h"
|
||||||
|
#include "KipProcess.h"
|
||||||
#include "PkiCertProcess.h"
|
#include "PkiCertProcess.h"
|
||||||
#include "EsTikProcess.h"
|
#include "EsTikProcess.h"
|
||||||
#include "AssetProcess.h"
|
#include "AssetProcess.h"
|
||||||
|
@ -40,96 +42,96 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
if (user_set.getFileType() == FILE_GC)
|
if (user_set.getFileType() == FILE_GC)
|
||||||
{
|
{
|
||||||
GameCardProcess xci;
|
GameCardProcess obj;
|
||||||
|
|
||||||
xci.setInputFile(inputFile);
|
obj.setInputFile(inputFile);
|
||||||
|
|
||||||
xci.setKeyCfg(user_set.getKeyCfg());
|
obj.setKeyCfg(user_set.getKeyCfg());
|
||||||
xci.setCliOutputMode(user_set.getCliOutputMode());
|
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||||
xci.setVerifyMode(user_set.isVerifyFile());
|
obj.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
if (user_set.getXciUpdatePath().isSet)
|
if (user_set.getXciUpdatePath().isSet)
|
||||||
xci.setPartitionForExtract(nn::hac::gc::kUpdatePartitionStr, user_set.getXciUpdatePath().var);
|
obj.setPartitionForExtract(nn::hac::gc::kUpdatePartitionStr, user_set.getXciUpdatePath().var);
|
||||||
if (user_set.getXciLogoPath().isSet)
|
if (user_set.getXciLogoPath().isSet)
|
||||||
xci.setPartitionForExtract(nn::hac::gc::kLogoPartitionStr, user_set.getXciLogoPath().var);
|
obj.setPartitionForExtract(nn::hac::gc::kLogoPartitionStr, user_set.getXciLogoPath().var);
|
||||||
if (user_set.getXciNormalPath().isSet)
|
if (user_set.getXciNormalPath().isSet)
|
||||||
xci.setPartitionForExtract(nn::hac::gc::kNormalPartitionStr, user_set.getXciNormalPath().var);
|
obj.setPartitionForExtract(nn::hac::gc::kNormalPartitionStr, user_set.getXciNormalPath().var);
|
||||||
if (user_set.getXciSecurePath().isSet)
|
if (user_set.getXciSecurePath().isSet)
|
||||||
xci.setPartitionForExtract(nn::hac::gc::kSecurePartitionStr, user_set.getXciSecurePath().var);
|
obj.setPartitionForExtract(nn::hac::gc::kSecurePartitionStr, user_set.getXciSecurePath().var);
|
||||||
xci.setListFs(user_set.isListFs());
|
obj.setListFs(user_set.isListFs());
|
||||||
|
|
||||||
xci.process();
|
obj.process();
|
||||||
}
|
}
|
||||||
else if (user_set.getFileType() == FILE_PARTITIONFS || user_set.getFileType() == FILE_NSP)
|
else if (user_set.getFileType() == FILE_PARTITIONFS || user_set.getFileType() == FILE_NSP)
|
||||||
{
|
{
|
||||||
PfsProcess pfs;
|
PfsProcess obj;
|
||||||
|
|
||||||
pfs.setInputFile(inputFile);
|
obj.setInputFile(inputFile);
|
||||||
pfs.setCliOutputMode(user_set.getCliOutputMode());
|
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||||
pfs.setVerifyMode(user_set.isVerifyFile());
|
obj.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
if (user_set.getFsPath().isSet)
|
if (user_set.getFsPath().isSet)
|
||||||
pfs.setExtractPath(user_set.getFsPath().var);
|
obj.setExtractPath(user_set.getFsPath().var);
|
||||||
pfs.setListFs(user_set.isListFs());
|
obj.setListFs(user_set.isListFs());
|
||||||
|
|
||||||
pfs.process();
|
obj.process();
|
||||||
}
|
}
|
||||||
else if (user_set.getFileType() == FILE_ROMFS)
|
else if (user_set.getFileType() == FILE_ROMFS)
|
||||||
{
|
{
|
||||||
RomfsProcess romfs;
|
RomfsProcess obj;
|
||||||
|
|
||||||
romfs.setInputFile(inputFile);
|
obj.setInputFile(inputFile);
|
||||||
romfs.setCliOutputMode(user_set.getCliOutputMode());
|
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||||
romfs.setVerifyMode(user_set.isVerifyFile());
|
obj.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
if (user_set.getFsPath().isSet)
|
if (user_set.getFsPath().isSet)
|
||||||
romfs.setExtractPath(user_set.getFsPath().var);
|
obj.setExtractPath(user_set.getFsPath().var);
|
||||||
romfs.setListFs(user_set.isListFs());
|
obj.setListFs(user_set.isListFs());
|
||||||
|
|
||||||
romfs.process();
|
obj.process();
|
||||||
}
|
}
|
||||||
else if (user_set.getFileType() == FILE_NCA)
|
else if (user_set.getFileType() == FILE_NCA)
|
||||||
{
|
{
|
||||||
NcaProcess nca;
|
NcaProcess obj;
|
||||||
|
|
||||||
nca.setInputFile(inputFile);
|
obj.setInputFile(inputFile);
|
||||||
nca.setKeyCfg(user_set.getKeyCfg());
|
obj.setKeyCfg(user_set.getKeyCfg());
|
||||||
nca.setCliOutputMode(user_set.getCliOutputMode());
|
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||||
nca.setVerifyMode(user_set.isVerifyFile());
|
obj.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
|
|
||||||
if (user_set.getNcaPart0Path().isSet)
|
if (user_set.getNcaPart0Path().isSet)
|
||||||
nca.setPartition0ExtractPath(user_set.getNcaPart0Path().var);
|
obj.setPartition0ExtractPath(user_set.getNcaPart0Path().var);
|
||||||
if (user_set.getNcaPart1Path().isSet)
|
if (user_set.getNcaPart1Path().isSet)
|
||||||
nca.setPartition1ExtractPath(user_set.getNcaPart1Path().var);
|
obj.setPartition1ExtractPath(user_set.getNcaPart1Path().var);
|
||||||
if (user_set.getNcaPart2Path().isSet)
|
if (user_set.getNcaPart2Path().isSet)
|
||||||
nca.setPartition2ExtractPath(user_set.getNcaPart2Path().var);
|
obj.setPartition2ExtractPath(user_set.getNcaPart2Path().var);
|
||||||
if (user_set.getNcaPart3Path().isSet)
|
if (user_set.getNcaPart3Path().isSet)
|
||||||
nca.setPartition3ExtractPath(user_set.getNcaPart3Path().var);
|
obj.setPartition3ExtractPath(user_set.getNcaPart3Path().var);
|
||||||
nca.setListFs(user_set.isListFs());
|
obj.setListFs(user_set.isListFs());
|
||||||
|
|
||||||
nca.process();
|
obj.process();
|
||||||
}
|
}
|
||||||
else if (user_set.getFileType() == FILE_META)
|
else if (user_set.getFileType() == FILE_META)
|
||||||
{
|
{
|
||||||
MetaProcess npdm;
|
MetaProcess obj;
|
||||||
|
|
||||||
npdm.setInputFile(inputFile);
|
obj.setInputFile(inputFile);
|
||||||
npdm.setKeyCfg(user_set.getKeyCfg());
|
obj.setKeyCfg(user_set.getKeyCfg());
|
||||||
npdm.setCliOutputMode(user_set.getCliOutputMode());
|
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||||
npdm.setVerifyMode(user_set.isVerifyFile());
|
obj.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
npdm.process();
|
obj.process();
|
||||||
}
|
}
|
||||||
else if (user_set.getFileType() == FILE_CNMT)
|
else if (user_set.getFileType() == FILE_CNMT)
|
||||||
{
|
{
|
||||||
CnmtProcess cnmt;
|
CnmtProcess obj;
|
||||||
|
|
||||||
cnmt.setInputFile(inputFile);
|
obj.setInputFile(inputFile);
|
||||||
cnmt.setCliOutputMode(user_set.getCliOutputMode());
|
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||||
cnmt.setVerifyMode(user_set.isVerifyFile());
|
obj.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
cnmt.process();
|
obj.process();
|
||||||
}
|
}
|
||||||
else if (user_set.getFileType() == FILE_NSO)
|
else if (user_set.getFileType() == FILE_NSO)
|
||||||
{
|
{
|
||||||
|
@ -170,36 +172,59 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
else if (user_set.getFileType() == FILE_NACP)
|
else if (user_set.getFileType() == FILE_NACP)
|
||||||
{
|
{
|
||||||
NacpProcess nacp;
|
NacpProcess obj;
|
||||||
|
|
||||||
nacp.setInputFile(inputFile);
|
obj.setInputFile(inputFile);
|
||||||
nacp.setCliOutputMode(user_set.getCliOutputMode());
|
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||||
nacp.setVerifyMode(user_set.isVerifyFile());
|
obj.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
nacp.process();
|
obj.process();
|
||||||
|
}
|
||||||
|
else if (user_set.getFileType() == FILE_INI)
|
||||||
|
{
|
||||||
|
IniProcess obj;
|
||||||
|
|
||||||
|
obj.setInputFile(inputFile);
|
||||||
|
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||||
|
obj.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
|
if (user_set.getKipExtractPath().isSet)
|
||||||
|
obj.setKipExtractPath(user_set.getKipExtractPath().var);
|
||||||
|
|
||||||
|
obj.process();
|
||||||
|
}
|
||||||
|
else if (user_set.getFileType() == FILE_KIP)
|
||||||
|
{
|
||||||
|
KipProcess obj;
|
||||||
|
|
||||||
|
obj.setInputFile(inputFile);
|
||||||
|
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||||
|
obj.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
|
obj.process();
|
||||||
}
|
}
|
||||||
else if (user_set.getFileType() == FILE_PKI_CERT)
|
else if (user_set.getFileType() == FILE_PKI_CERT)
|
||||||
{
|
{
|
||||||
PkiCertProcess cert;
|
PkiCertProcess obj;
|
||||||
|
|
||||||
cert.setInputFile(inputFile);
|
obj.setInputFile(inputFile);
|
||||||
cert.setKeyCfg(user_set.getKeyCfg());
|
obj.setKeyCfg(user_set.getKeyCfg());
|
||||||
cert.setCliOutputMode(user_set.getCliOutputMode());
|
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||||
cert.setVerifyMode(user_set.isVerifyFile());
|
obj.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
cert.process();
|
obj.process();
|
||||||
}
|
}
|
||||||
else if (user_set.getFileType() == FILE_ES_TIK)
|
else if (user_set.getFileType() == FILE_ES_TIK)
|
||||||
{
|
{
|
||||||
EsTikProcess tik;
|
EsTikProcess obj;
|
||||||
|
|
||||||
tik.setInputFile(inputFile);
|
obj.setInputFile(inputFile);
|
||||||
tik.setKeyCfg(user_set.getKeyCfg());
|
obj.setKeyCfg(user_set.getKeyCfg());
|
||||||
tik.setCertificateChain(user_set.getCertificateChain());
|
obj.setCertificateChain(user_set.getCertificateChain());
|
||||||
tik.setCliOutputMode(user_set.getCliOutputMode());
|
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||||
tik.setVerifyMode(user_set.isVerifyFile());
|
obj.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
tik.process();
|
obj.process();
|
||||||
}
|
}
|
||||||
else if (user_set.getFileType() == FILE_HB_ASSET)
|
else if (user_set.getFileType() == FILE_HB_ASSET)
|
||||||
{
|
{
|
||||||
|
@ -220,6 +245,10 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
obj.process();
|
obj.process();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw fnd::Exception("main", "Unhandled file type");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (const fnd::Exception& e) {
|
catch (const fnd::Exception& e) {
|
||||||
printf("\n\n%s\n", e.what());
|
printf("\n\n%s\n", e.what());
|
||||||
|
|
Loading…
Reference in a new issue