2018-08-07 07:17:51 +00:00
|
|
|
#include <nn/hac/NpdmBinary.h>
|
2017-07-17 08:21:39 +00:00
|
|
|
|
2018-06-27 05:03:46 +00:00
|
|
|
#include <fnd/SimpleTextOutput.h>
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
nn::hac::NpdmBinary::NpdmBinary()
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
nn::hac::NpdmBinary::NpdmBinary(const NpdmBinary & other) :
|
2018-06-29 06:45:36 +00:00
|
|
|
NpdmBinary()
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
2018-06-24 08:18:54 +00:00
|
|
|
*this = other;
|
2017-07-17 08:21:39 +00:00
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
void nn::hac::NpdmBinary::operator=(const NpdmBinary & other)
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
2018-06-29 06:45:36 +00:00
|
|
|
mRawBinary = other.mRawBinary;
|
|
|
|
mInstructionType = other.mInstructionType;
|
|
|
|
mProcAddressSpaceType = other.mProcAddressSpaceType;
|
|
|
|
mMainThreadPriority = other.mMainThreadPriority;
|
|
|
|
mMainThreadCpuId = other.mMainThreadCpuId;
|
|
|
|
mVersion = other.mVersion;
|
|
|
|
mMainThreadStackSize = other.mMainThreadStackSize;
|
|
|
|
mName = other.mName;
|
|
|
|
mProductCode = other.mProductCode;
|
|
|
|
mAci = other.mAci;
|
|
|
|
mAcid = other.mAcid;
|
2017-07-17 08:21:39 +00:00
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
bool nn::hac::NpdmBinary::operator==(const NpdmBinary & other) const
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
2018-06-29 06:45:36 +00:00
|
|
|
return (mInstructionType == other.mInstructionType) \
|
|
|
|
&& (mProcAddressSpaceType == other.mProcAddressSpaceType) \
|
|
|
|
&& (mMainThreadPriority == other.mMainThreadPriority) \
|
|
|
|
&& (mMainThreadCpuId == other.mMainThreadCpuId) \
|
|
|
|
&& (mVersion == other.mVersion) \
|
|
|
|
&& (mMainThreadStackSize == other.mMainThreadStackSize) \
|
|
|
|
&& (mName == other.mName) \
|
|
|
|
&& (mProductCode == other.mProductCode) \
|
2018-06-24 08:18:54 +00:00
|
|
|
&& (mAci == other.mAci) \
|
|
|
|
&& (mAcid == other.mAcid);
|
2017-07-17 08:21:39 +00:00
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
bool nn::hac::NpdmBinary::operator!=(const NpdmBinary & other) const
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
2018-06-24 08:18:54 +00:00
|
|
|
return !(*this == other);
|
2017-07-17 08:21:39 +00:00
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
void nn::hac::NpdmBinary::toBytes()
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
2018-06-29 06:45:36 +00:00
|
|
|
if (mAcid.getBytes().size() == 0)
|
|
|
|
mAcid.toBytes();
|
|
|
|
|
|
|
|
if (mAci.getBytes().size() == 0)
|
|
|
|
mAci.toBytes();
|
|
|
|
|
|
|
|
|
|
|
|
// determine section layout
|
|
|
|
struct sLayout {
|
|
|
|
uint32_t offset, size;
|
|
|
|
} acid, aci;
|
|
|
|
|
2018-07-01 05:43:01 +00:00
|
|
|
acid.offset = (uint32_t)align(sizeof(sNpdmHeader), npdm::kSectionAlignSize);
|
2018-06-29 06:45:36 +00:00
|
|
|
acid.size = (uint32_t)mAcid.getBytes().size();
|
2018-07-10 15:23:05 +00:00
|
|
|
aci.offset = (uint32_t)(acid.offset + align(acid.size, npdm::kSectionAlignSize));
|
2018-06-29 06:45:36 +00:00
|
|
|
aci.size = (uint32_t)mAci.getBytes().size();
|
|
|
|
|
|
|
|
|
|
|
|
// get total size
|
|
|
|
size_t total_size = _MAX(_MAX(acid.offset + acid.size, aci.offset + aci.size), align(sizeof(sNpdmHeader), npdm::kSectionAlignSize));
|
|
|
|
|
|
|
|
mRawBinary.alloc(total_size);
|
|
|
|
sNpdmHeader* hdr = (sNpdmHeader*)mRawBinary.data();
|
|
|
|
|
|
|
|
// set type
|
|
|
|
hdr->st_magic = npdm::kNpdmStructMagic;
|
|
|
|
|
|
|
|
// set variables
|
|
|
|
byte_t flag = ((byte_t)(mInstructionType & 1) | (byte_t)((mProcAddressSpaceType & 3) << 1)) & 0xf;
|
|
|
|
hdr->flags = flag;
|
|
|
|
hdr->main_thread_priority = mMainThreadPriority;
|
|
|
|
hdr->main_thread_cpu_id = mMainThreadCpuId;
|
|
|
|
hdr->version = mVersion;
|
|
|
|
hdr->main_thread_stack_size = mMainThreadStackSize;
|
|
|
|
strncpy(hdr->name, mName.c_str(), npdm::kNameMaxLen);
|
|
|
|
strncpy(hdr->product_code, mProductCode.c_str(), npdm::kProductCodeMaxLen);
|
|
|
|
|
|
|
|
// set offset/size
|
|
|
|
hdr->aci.offset = aci.offset;
|
|
|
|
hdr->aci.size = aci.size;
|
|
|
|
hdr->acid.offset = acid.offset;
|
|
|
|
hdr->acid.size = acid.size;
|
|
|
|
|
|
|
|
// write aci & acid
|
|
|
|
if (mAci.getBytes().size() > 0)
|
|
|
|
{
|
|
|
|
memcpy(mRawBinary.data() + aci.offset, mAci.getBytes().data(), mAci.getBytes().size());
|
|
|
|
}
|
|
|
|
if (mAcid.getBytes().size() > 0)
|
|
|
|
{
|
|
|
|
memcpy(mRawBinary.data() + acid.offset, mAcid.getBytes().data(), mAcid.getBytes().size());
|
|
|
|
}
|
2017-07-17 08:21:39 +00:00
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
void nn::hac::NpdmBinary::fromBytes(const byte_t* data, size_t len)
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
2018-06-29 06:45:36 +00:00
|
|
|
// check size
|
|
|
|
if (len < sizeof(sNpdmHeader))
|
|
|
|
{
|
|
|
|
throw fnd::Exception(kModuleName, "NPDM binary is too small");
|
|
|
|
}
|
|
|
|
|
|
|
|
// clear variables
|
2017-07-17 08:21:39 +00:00
|
|
|
clear();
|
|
|
|
|
2018-06-29 06:45:36 +00:00
|
|
|
// save a copy of the header
|
|
|
|
sNpdmHeader hdr;
|
|
|
|
memcpy((void*)&hdr, data, sizeof(sNpdmHeader));
|
|
|
|
|
|
|
|
// check magic
|
|
|
|
if (hdr.st_magic.get() != npdm::kNpdmStructMagic)
|
|
|
|
{
|
|
|
|
throw fnd::Exception(kModuleName, "NPDM header corrupt");
|
|
|
|
}
|
|
|
|
|
|
|
|
// save variables
|
|
|
|
byte_t flag = hdr.flags & 0xf;
|
|
|
|
mInstructionType = (npdm::InstructionType)(flag & 1);
|
|
|
|
mProcAddressSpaceType = (npdm::ProcAddrSpaceType)((flag >> 1) & 3);
|
|
|
|
mMainThreadPriority = hdr.main_thread_priority;
|
|
|
|
mMainThreadCpuId = hdr.main_thread_cpu_id;
|
|
|
|
mVersion = hdr.version.get();
|
|
|
|
mMainThreadStackSize = hdr.main_thread_stack_size.get();
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
// total size
|
|
|
|
size_t total_size = _MAX(_MAX(hdr.acid.offset.get() + hdr.acid.size.get(), hdr.aci.offset.get() + hdr.aci.size.get()), sizeof(sNpdmHeader));
|
2017-07-17 08:21:39 +00:00
|
|
|
|
|
|
|
// check size
|
2018-06-29 06:45:36 +00:00
|
|
|
if (total_size > len)
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
|
|
|
throw fnd::Exception(kModuleName, "NPDM binary too small");
|
|
|
|
}
|
|
|
|
|
|
|
|
// save local copy
|
2018-06-29 06:45:36 +00:00
|
|
|
mRawBinary.alloc(total_size);
|
2018-06-24 08:18:54 +00:00
|
|
|
memcpy(mRawBinary.data(), data, mRawBinary.size());
|
2017-07-17 08:21:39 +00:00
|
|
|
|
|
|
|
// import Aci/Acid
|
2018-06-29 06:45:36 +00:00
|
|
|
if (hdr.aci.size.get())
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
2018-06-29 06:45:36 +00:00
|
|
|
mAci.fromBytes(mRawBinary.data() + hdr.aci.offset.get(), hdr.aci.size.get());
|
2017-07-17 08:21:39 +00:00
|
|
|
}
|
2018-06-29 06:45:36 +00:00
|
|
|
if (hdr.acid.size.get())
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
2018-06-29 06:45:36 +00:00
|
|
|
mAcid.fromBytes(mRawBinary.data() + hdr.acid.offset.get(), hdr.acid.size.get());
|
2018-06-24 08:18:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
const fnd::Vec<byte_t>& nn::hac::NpdmBinary::getBytes() const
|
2018-06-24 08:18:54 +00:00
|
|
|
{
|
|
|
|
return mRawBinary;
|
2017-07-17 08:21:39 +00:00
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
void nn::hac::NpdmBinary::clear()
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
2018-06-29 06:45:36 +00:00
|
|
|
mRawBinary.clear();
|
|
|
|
mInstructionType = npdm::INSTR_64BIT;
|
|
|
|
mProcAddressSpaceType = npdm::ADDR_SPACE_64BIT;
|
|
|
|
mMainThreadPriority = 0;
|
|
|
|
mMainThreadCpuId = 0;
|
|
|
|
mVersion = 0;
|
|
|
|
mMainThreadStackSize = 0;
|
|
|
|
mName.clear();
|
|
|
|
mProductCode.clear();
|
2017-07-17 08:21:39 +00:00
|
|
|
mAci.clear();
|
|
|
|
mAcid.clear();
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
nn::hac::npdm::InstructionType nn::hac::NpdmBinary::getInstructionType() const
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
return mInstructionType;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
void nn::hac::NpdmBinary::setInstructionType(npdm::InstructionType type)
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
mInstructionType = type;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
nn::hac::npdm::ProcAddrSpaceType nn::hac::NpdmBinary::getProcAddressSpaceType() const
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
return mProcAddressSpaceType;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
void nn::hac::NpdmBinary::setProcAddressSpaceType(npdm::ProcAddrSpaceType type)
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
mProcAddressSpaceType = type;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
byte_t nn::hac::NpdmBinary::getMainThreadPriority() const
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
return mMainThreadPriority;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
void nn::hac::NpdmBinary::setMainThreadPriority(byte_t priority)
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
if (priority > npdm::kMaxPriority)
|
|
|
|
{
|
|
|
|
throw fnd::Exception(kModuleName, "Illegal main thread priority (range 0-63)");
|
|
|
|
}
|
|
|
|
|
|
|
|
mMainThreadPriority = priority;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
byte_t nn::hac::NpdmBinary::getMainThreadCpuId() const
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
return mMainThreadCpuId;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
void nn::hac::NpdmBinary::setMainThreadCpuId(byte_t core_num)
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
mMainThreadCpuId = core_num;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
uint32_t nn::hac::NpdmBinary::getVersion() const
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
return mVersion;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
void nn::hac::NpdmBinary::setVersion(uint32_t version)
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
mVersion = version;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
uint32_t nn::hac::NpdmBinary::getMainThreadStackSize() const
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
return mMainThreadStackSize;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
void nn::hac::NpdmBinary::setMainThreadStackSize(uint32_t size)
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
mMainThreadStackSize = size;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
const std::string & nn::hac::NpdmBinary::getName() const
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
return mName;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
void nn::hac::NpdmBinary::setName(const std::string & name)
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
if (name.length() > npdm::kNameMaxLen)
|
|
|
|
{
|
|
|
|
throw fnd::Exception(kModuleName, "Name is too long");
|
|
|
|
}
|
|
|
|
|
|
|
|
mName = name;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
const std::string & nn::hac::NpdmBinary::getProductCode() const
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
return mProductCode;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
void nn::hac::NpdmBinary::setProductCode(const std::string & product_code)
|
2018-06-29 06:45:36 +00:00
|
|
|
{
|
|
|
|
if (product_code.length() > npdm::kProductCodeMaxLen)
|
|
|
|
{
|
|
|
|
throw fnd::Exception(kModuleName, "Product Code is too long");
|
|
|
|
}
|
|
|
|
|
|
|
|
mProductCode = product_code;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
const nn::hac::AccessControlInfoBinary & nn::hac::NpdmBinary::getAci() const
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
|
|
|
return mAci;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
void nn::hac::NpdmBinary::setAci(const AccessControlInfoBinary & aci)
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
|
|
|
mAci = aci;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
const nn::hac::AccessControlInfoDescBinary & nn::hac::NpdmBinary::getAcid() const
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
|
|
|
return mAcid;
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:17:51 +00:00
|
|
|
void nn::hac::NpdmBinary::setAcid(const AccessControlInfoDescBinary & acid)
|
2017-07-17 08:21:39 +00:00
|
|
|
{
|
|
|
|
mAcid = acid;
|
2018-06-24 08:18:54 +00:00
|
|
|
}
|