[hac] Add IniHeader & KernelInitialProcessHeader

This commit is contained in:
jakcron 2018-10-27 15:46:17 +08:00
parent 44a9f7744c
commit bac8fb57ff
6 changed files with 729 additions and 0 deletions

View 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;
};
}
}

View 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;
};
}
}

View 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)
}
}

View 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)
}
}

View 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;
}

View file

@ -0,0 +1,341 @@
#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());
//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;
}