nstool/lib/libnx/source/NpdmHeader.cpp

285 lines
6.4 KiB
C++
Raw Normal View History

#include <nx/NpdmHeader.h>
2017-07-07 00:18:33 +00:00
nx::NpdmHeader::NpdmHeader()
{
clear();
2017-07-07 00:18:33 +00:00
}
nx::NpdmHeader::NpdmHeader(const NpdmHeader & other)
{
copyFrom(other);
}
2018-03-22 05:26:22 +00:00
nx::NpdmHeader::NpdmHeader(const byte_t * bytes, size_t len)
2017-07-07 00:18:33 +00:00
{
importBinary(bytes, len);
2017-07-07 00:18:33 +00:00
}
bool nx::NpdmHeader::operator==(const NpdmHeader & other) const
{
return isEqual(other);
}
bool nx::NpdmHeader::operator!=(const NpdmHeader & other) const
{
return isEqual(other);
}
void nx::NpdmHeader::operator=(const NpdmHeader & other)
{
copyFrom(other);
}
2018-03-22 05:26:22 +00:00
const byte_t * nx::NpdmHeader::getBytes() const
2017-07-07 00:18:33 +00:00
{
return mBinaryBlob.getBytes();
}
size_t nx::NpdmHeader::getSize() const
{
return mBinaryBlob.getSize();
}
void nx::NpdmHeader::calculateOffsets()
{
mAcidPos.offset = align(sizeof(sNpdmHeader), npdm::kNpdmAlignSize);
mAciPos.offset = mAcidPos.offset + align(mAcidPos.size, npdm::kNpdmAlignSize);
2017-07-07 00:18:33 +00:00
}
bool nx::NpdmHeader::isEqual(const NpdmHeader & other) const
{
return (mInstructionType == other.mInstructionType) \
&& (mProcAddressSpaceType == other.mProcAddressSpaceType) \
&& (mMainThreadPriority == other.mMainThreadPriority) \
&& (mMainThreadCpuId == other.mMainThreadCpuId) \
2017-07-07 00:18:33 +00:00
&& (mVersion == other.mVersion) \
&& (mMainThreadStackSize == other.mMainThreadStackSize) \
&& (mName == other.mName) \
&& (mProductCode == other.mProductCode) \
&& (mAciPos == other.mAciPos) \
&& (mAcidPos == other.mAcidPos);
}
void nx::NpdmHeader::copyFrom(const NpdmHeader & other)
{
if (other.getSize())
{
importBinary(other.getBytes(), other.getSize());
}
else
{
mInstructionType = other.mInstructionType;
mProcAddressSpaceType = other.mProcAddressSpaceType;
mMainThreadPriority = other.mMainThreadPriority;
mMainThreadCpuId = other.mMainThreadCpuId;
2017-07-07 00:18:33 +00:00
mVersion = other.mVersion;
mMainThreadStackSize = other.mMainThreadStackSize;
mName = other.mName;
mProductCode = other.mProductCode;
mAciPos = other.mAciPos;
mAcidPos = other.mAcidPos;
}
}
void nx::NpdmHeader::exportBinary()
{
mBinaryBlob.alloc(sizeof(sNpdmHeader));
sNpdmHeader* hdr = (sNpdmHeader*)mBinaryBlob.getBytes();
hdr->set_signature(npdm::kNpdmStructSig.c_str());
2018-03-22 05:26:22 +00:00
byte_t flag = ((byte_t)(mInstructionType & 1) | (byte_t)((mProcAddressSpaceType & 3) << 1)) & 0xf;
2017-07-07 00:18:33 +00:00
hdr->set_flags(flag);
hdr->set_main_thread_priority(mMainThreadPriority);
hdr->set_main_thread_cpu_id(mMainThreadCpuId);
2017-07-07 00:18:33 +00:00
hdr->set_version(mVersion);
hdr->set_main_thread_stack_size(mMainThreadStackSize);
hdr->set_name(mName.c_str());
hdr->set_product_code(mProductCode.c_str());
calculateOffsets();
hdr->aci().set_offset(mAciPos.offset);
hdr->aci().set_size(mAciPos.size);
hdr->acid().set_offset(mAcidPos.offset);
hdr->acid().set_size(mAcidPos.size);
}
2018-03-22 05:26:22 +00:00
void nx::NpdmHeader::importBinary(const byte_t * bytes, size_t len)
2017-07-07 00:18:33 +00:00
{
if (len < sizeof(sNpdmHeader))
{
throw fnd::Exception(kModuleName, "NPDM header too small");
}
clear();
2017-07-07 00:18:33 +00:00
mBinaryBlob.alloc(sizeof(sNpdmHeader));
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
sNpdmHeader* hdr = (sNpdmHeader*)mBinaryBlob.getBytes();
if (memcmp(npdm::kNpdmStructSig.c_str(), hdr->signature(), 4) != 0)
2017-07-07 00:18:33 +00:00
{
throw fnd::Exception(kModuleName, "NPDM header corrupt");
}
2018-03-22 05:26:22 +00:00
byte_t flag = hdr->flags() & 0xf;
mInstructionType = (npdm::InstructionType)(flag & 1);
mProcAddressSpaceType = (npdm::ProcAddrSpaceType)((flag >> 1) & 3);
2017-07-07 00:18:33 +00:00
mMainThreadPriority = hdr->main_thread_priority();
mMainThreadCpuId = hdr->main_thread_cpu_id();
2017-07-07 00:18:33 +00:00
mVersion = hdr->version();
mMainThreadStackSize = hdr->main_thread_stack_size();
mName = std::string(hdr->name(), npdm::kNameMaxLen);
if (mName[0] == '\0')
{
mName.clear();
}
mProductCode = std::string(hdr->product_code(), npdm::kProductCodeMaxLen);
if (mProductCode[0] == '\0')
{
mProductCode.clear();
}
2017-07-07 00:18:33 +00:00
mAciPos.offset = hdr->aci().offset();
mAciPos.size = hdr->aci().size();
mAcidPos.offset = hdr->acid().offset();
mAcidPos.size = hdr->acid().size();
}
void nx::NpdmHeader::clear()
2017-07-07 00:18:33 +00:00
{
mBinaryBlob.clear();
mInstructionType = npdm::INSTR_64BIT;
mProcAddressSpaceType = npdm::ADDR_SPACE_64BIT;
mMainThreadPriority = 0;
mMainThreadCpuId = 0;
mVersion = 0;
mMainThreadStackSize = 0;
mName.clear();
mProductCode.clear();
mAciPos.offset = 0;
mAciPos.size = 0;
mAcidPos.offset = 0;
mAcidPos.size = 0;
2017-07-07 00:18:33 +00:00
}
size_t nx::NpdmHeader::getNpdmSize() const
{
return MAX(mAcidPos.offset + mAcidPos.size, mAciPos.offset + mAciPos.size);
}
nx::npdm::InstructionType nx::NpdmHeader::getInstructionType() const
2017-07-07 00:18:33 +00:00
{
return mInstructionType;
}
void nx::NpdmHeader::setInstructionType(npdm::InstructionType type)
2017-07-07 00:18:33 +00:00
{
mInstructionType = type;
}
nx::npdm::ProcAddrSpaceType nx::NpdmHeader::getProcAddressSpaceType() const
2017-07-07 00:18:33 +00:00
{
return mProcAddressSpaceType;
}
void nx::NpdmHeader::setProcAddressSpaceType(npdm::ProcAddrSpaceType type)
2017-07-07 00:18:33 +00:00
{
mProcAddressSpaceType = type;
}
2018-03-22 05:26:22 +00:00
byte_t nx::NpdmHeader::getMainThreadPriority() const
2017-07-07 00:18:33 +00:00
{
return mMainThreadPriority;
}
2018-03-22 05:26:22 +00:00
void nx::NpdmHeader::setMainThreadPriority(byte_t priority)
2017-07-07 00:18:33 +00:00
{
if (priority > npdm::kMaxPriority)
2017-07-07 00:18:33 +00:00
{
throw fnd::Exception(kModuleName, "Illegal main thread priority (range 0-63)");
}
mMainThreadPriority = priority;
}
2018-03-22 05:26:22 +00:00
byte_t nx::NpdmHeader::getMainThreadCpuId() const
2017-07-07 00:18:33 +00:00
{
return mMainThreadCpuId;
2017-07-07 00:18:33 +00:00
}
2018-03-22 05:26:22 +00:00
void nx::NpdmHeader::setMainThreadCpuId(byte_t core_num)
2017-07-07 00:18:33 +00:00
{
mMainThreadCpuId = core_num;
2017-07-07 00:18:33 +00:00
}
2018-03-22 05:26:22 +00:00
uint32_t nx::NpdmHeader::getVersion() const
2017-07-07 00:18:33 +00:00
{
return mVersion;
}
2018-03-22 05:26:22 +00:00
void nx::NpdmHeader::setVersion(uint32_t version)
2017-07-07 00:18:33 +00:00
{
mVersion = version;
}
2018-03-22 05:26:22 +00:00
uint32_t nx::NpdmHeader::getMainThreadStackSize() const
2017-07-07 00:18:33 +00:00
{
return mMainThreadStackSize;
}
2018-03-22 05:26:22 +00:00
void nx::NpdmHeader::setMainThreadStackSize(uint32_t size)
2017-07-07 00:18:33 +00:00
{
mMainThreadStackSize = size;
}
const std::string & nx::NpdmHeader::getName() const
{
return mName;
}
void nx::NpdmHeader::setName(const std::string & name)
{
if (name.length() > npdm::kNameMaxLen)
2017-07-07 00:18:33 +00:00
{
throw fnd::Exception(kModuleName, "Name is too long");
}
mName = name;
}
const std::string & nx::NpdmHeader::getProductCode() const
{
return mProductCode;
}
void nx::NpdmHeader::setProductCode(const std::string & product_code)
{
if (product_code.length() > npdm::kProductCodeMaxLen)
2017-07-07 00:18:33 +00:00
{
throw fnd::Exception(kModuleName, "Product Code is too long");
}
mProductCode = product_code;
}
const nx::NpdmHeader::sSection & nx::NpdmHeader::getAciPos() const
{
return mAciPos;
}
void nx::NpdmHeader::setAciSize(size_t size)
2017-07-07 00:18:33 +00:00
{
mAciPos.size = size;
}
const nx::NpdmHeader::sSection & nx::NpdmHeader::getAcidPos() const
{
return mAcidPos;
}
void nx::NpdmHeader::setAcidSize(size_t size)
2017-07-07 00:18:33 +00:00
{
mAcidPos.size = size;
}