From 30b3dd6063fa91f6a777ce35894092ced2720f06 Mon Sep 17 00:00:00 2001 From: jakcron Date: Thu, 13 Jul 2017 00:02:10 +1000 Subject: [PATCH] [nx] Implement KcBinary and supporting classes. --- lib/nx/HandleTableSizeHandler.cpp | 79 ++++++++++ lib/nx/HandleTableSizeHandler.h | 38 +++++ lib/nx/IKernelCapabilityHandler.h | 4 +- lib/nx/InteruptEntry.cpp | 35 ++--- lib/nx/InteruptEntry.h | 16 +- lib/nx/InteruptHandler.cpp | 121 ++++++++++++++ lib/nx/InteruptHandler.h | 37 +++++ lib/nx/KcBinary.cpp | 252 ++++++++++++++++++++++++++++++ lib/nx/KcBinary.h | 86 ++++++++++ lib/nx/KernelVersionHandler.cpp | 92 +++++++++++ lib/nx/KernelVersionHandler.h | 40 +++++ lib/nx/MemoryMappingHandler.cpp | 147 +++++++++++++++++ lib/nx/MemoryMappingHandler.h | 69 ++++++++ lib/nx/MemoryPageEntry.cpp | 4 +- lib/nx/MemoryPageEntry.h | 4 +- lib/nx/MiscFlagsEntry.h | 20 --- lib/nx/MiscFlagsHandler.cpp | 64 ++++++++ lib/nx/MiscFlagsHandler.h | 56 +++++++ lib/nx/MiscParamsHandler.cpp | 80 ++++++++++ lib/nx/MiscParamsHandler.h | 38 +++++ lib/nx/NpdmFile.h | 9 ++ lib/nx/NpdmHeader.h | 8 +- lib/nx/SystemCallHandler.cpp | 123 +++++++++++++++ lib/nx/SystemCallHandler.h | 38 +++++ lib/nx/ThreadInfoHandler.cpp | 115 ++++++++++++++ lib/nx/ThreadInfoHandler.h | 44 ++++++ lib/nx/nx.vcxproj | 18 +++ lib/nx/nx.vcxproj.filters | 54 +++++++ 28 files changed, 1630 insertions(+), 61 deletions(-) create mode 100644 lib/nx/HandleTableSizeHandler.cpp create mode 100644 lib/nx/HandleTableSizeHandler.h create mode 100644 lib/nx/InteruptHandler.cpp create mode 100644 lib/nx/InteruptHandler.h create mode 100644 lib/nx/KcBinary.cpp create mode 100644 lib/nx/KcBinary.h create mode 100644 lib/nx/KernelVersionHandler.cpp create mode 100644 lib/nx/KernelVersionHandler.h create mode 100644 lib/nx/MemoryMappingHandler.cpp create mode 100644 lib/nx/MemoryMappingHandler.h create mode 100644 lib/nx/MiscFlagsHandler.cpp create mode 100644 lib/nx/MiscFlagsHandler.h create mode 100644 lib/nx/MiscParamsHandler.cpp create mode 100644 lib/nx/MiscParamsHandler.h create mode 100644 lib/nx/NpdmFile.h create mode 100644 lib/nx/SystemCallHandler.cpp create mode 100644 lib/nx/SystemCallHandler.h create mode 100644 lib/nx/ThreadInfoHandler.cpp create mode 100644 lib/nx/ThreadInfoHandler.h diff --git a/lib/nx/HandleTableSizeHandler.cpp b/lib/nx/HandleTableSizeHandler.cpp new file mode 100644 index 0000000..1fe65b8 --- /dev/null +++ b/lib/nx/HandleTableSizeHandler.cpp @@ -0,0 +1,79 @@ +#include "HandleTableSizeHandler.h" + + + +nx::HandleTableSizeHandler::HandleTableSizeHandler() : + mIsSet(false), + mEntry(0) +{} + +bool nx::HandleTableSizeHandler::operator==(const HandleTableSizeHandler & other) const +{ + return isEqual(other); +} + +bool nx::HandleTableSizeHandler::operator!=(const HandleTableSizeHandler & other) const +{ + return !isEqual(other); +} + +void nx::HandleTableSizeHandler::operator=(const HandleTableSizeHandler & other) +{ + copyFrom(other); +} + +void nx::HandleTableSizeHandler::importKernelCapabilityList(const fnd::List& caps) +{ + if (caps.getSize() > kMaxKernelCapNum) + { + throw fnd::Exception(kModuleName, "Too many kernel capabilities"); + } + + if (caps.getSize() == 0) + return; + + mEntry.setKernelCapability(caps[0]); + mIsSet = true; +} + +void nx::HandleTableSizeHandler::exportKernelCapabilityList(fnd::List& caps) const +{ + if (isSet() == false) + return; + + caps.addElement(mEntry.getKernelCapability()); +} + +void nx::HandleTableSizeHandler::clear() +{ + mIsSet = false; + mEntry.setHandleTableSize(0); +} + +bool nx::HandleTableSizeHandler::isSet() const +{ + return mIsSet; +} + +u16 nx::HandleTableSizeHandler::getHandleTableSize() const +{ + return mEntry.getHandleTableSize(); +} + +void nx::HandleTableSizeHandler::setHandleTableSize(u16 size) +{ + mEntry.setHandleTableSize(size); + mIsSet = true; +} + +void nx::HandleTableSizeHandler::copyFrom(const HandleTableSizeHandler & other) +{ + mIsSet = other.mIsSet; + mEntry.setKernelCapability(other.mEntry.getKernelCapability()); +} + +bool nx::HandleTableSizeHandler::isEqual(const HandleTableSizeHandler & other) const +{ + return (mIsSet == other.mIsSet) \ + && (mEntry.getKernelCapability() == other.mEntry.getKernelCapability()); +} diff --git a/lib/nx/HandleTableSizeHandler.h b/lib/nx/HandleTableSizeHandler.h new file mode 100644 index 0000000..adbaca2 --- /dev/null +++ b/lib/nx/HandleTableSizeHandler.h @@ -0,0 +1,38 @@ +#pragma once +#include +#include + +namespace nx +{ + class HandleTableSizeHandler : + public IKernelCapabilityHandler + { + public: + HandleTableSizeHandler(); + + bool operator==(const HandleTableSizeHandler& other) const; + bool operator!=(const HandleTableSizeHandler& other) const; + void operator=(const HandleTableSizeHandler& other); + + // kernel capabilty list in/out + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; + void clear(); + bool isSet() const; + + // variables + u16 getHandleTableSize() const; + void setHandleTableSize(u16 size); + + private: + const std::string kModuleName = "HANDLE_TABLE_SIZE_HANDLER"; + static const size_t kMaxKernelCapNum = 1; + + bool mIsSet; + HandleTableSizeEntry mEntry; + + void copyFrom(const HandleTableSizeHandler& other); + bool isEqual(const HandleTableSizeHandler& other) const; + }; +} + diff --git a/lib/nx/IKernelCapabilityHandler.h b/lib/nx/IKernelCapabilityHandler.h index 4b97ac8..40e2c57 100644 --- a/lib/nx/IKernelCapabilityHandler.h +++ b/lib/nx/IKernelCapabilityHandler.h @@ -9,7 +9,9 @@ namespace nx { public: virtual void importKernelCapabilityList(const fnd::List& caps) = 0; - virtual const fnd::List& exportKernelCapabilityList() = 0; + virtual void exportKernelCapabilityList(fnd::List& caps) const = 0; + virtual void clear() = 0; + virtual bool isSet() const = 0; }; } diff --git a/lib/nx/InteruptEntry.cpp b/lib/nx/InteruptEntry.cpp index f29c2bf..63b8bee 100644 --- a/lib/nx/InteruptEntry.cpp +++ b/lib/nx/InteruptEntry.cpp @@ -20,8 +20,8 @@ nx::InteruptEntry::InteruptEntry(u32 interupt0, u32 interupt1) : mCap(kCapId), mInterupt{ 0,0 } { - setInterupt0(interupt0); - setInterupt1(interupt1); + setInterupt(0, interupt0); + setInterupt(1, interupt1); } const nx::KernelCapability & nx::InteruptEntry::getKernelCapability() const @@ -40,34 +40,23 @@ void nx::InteruptEntry::setKernelCapability(const KernelCapability & kernel_cap) processCapField(); } -u32 nx::InteruptEntry::getInterupt0() const +u32 nx::InteruptEntry::operator[](size_t index) const { - return mInterupt[0]; + return getInterupt(index); } -void nx::InteruptEntry::setInterupt0(u32 interupt) +u32 nx::InteruptEntry::getInterupt(size_t index) const +{ + return mInterupt[index % kInteruptNum]; +} + +void nx::InteruptEntry::setInterupt(size_t index, u32 interupt) { if (interupt > kInteruptMax) { throw fnd::Exception(kModuleName, "Illegal interupt value."); } - mInterupt[0] = interupt; + mInterupt[index % kInteruptNum] = interupt; updateCapField(); -} - -u32 nx::InteruptEntry::getInterupt1() const -{ - return mInterupt[1]; -} - -void nx::InteruptEntry::setInterupt1(u32 interupt) -{ - if (interupt > kInteruptMax) - { - throw fnd::Exception(kModuleName, "Illegal interupt value."); - } - - mInterupt[1] = interupt; - updateCapField(); -} +} \ No newline at end of file diff --git a/lib/nx/InteruptEntry.h b/lib/nx/InteruptEntry.h index cf86a00..c6ebbb8 100644 --- a/lib/nx/InteruptEntry.h +++ b/lib/nx/InteruptEntry.h @@ -8,6 +8,10 @@ namespace nx class InteruptEntry { public: + static const u32 kInteruptBits = 10; + static const u32 kInteruptMax = BIT(kInteruptBits) - 1; + static const u32 kInteruptNum = 2; + InteruptEntry(); InteruptEntry(const KernelCapability& kernel_cap); InteruptEntry(u32 interupt0, u32 interupt1); @@ -17,19 +21,17 @@ namespace nx void setKernelCapability(const KernelCapability& kernel_cap); // variables - u32 getInterupt0() const; - void setInterupt0(u32 interupt); - u32 getInterupt1() const; - void setInterupt1(u32 interupt); + u32 operator[](size_t index) const; + + u32 getInterupt(size_t index) const; + void setInterupt(size_t index, u32 interupt); private: const std::string kModuleName = "INTERUPT_ENTRY"; static const KernelCapability::KernelCapId kCapId = KernelCapability::KC_ENABLE_INTERUPTS; - static const u32 kInteruptBits = 10; - static const u32 kInteruptMax = BIT(kInteruptBits) - 1; KernelCapability mCap; - u32 mInterupt[2]; + u32 mInterupt[kInteruptNum]; inline void updateCapField() { diff --git a/lib/nx/InteruptHandler.cpp b/lib/nx/InteruptHandler.cpp new file mode 100644 index 0000000..85b1498 --- /dev/null +++ b/lib/nx/InteruptHandler.cpp @@ -0,0 +1,121 @@ +#include "InteruptHandler.h" + + + +nx::InteruptHandler::InteruptHandler() : + mIsSet(false), + mInterupts() +{} + +bool nx::InteruptHandler::operator==(const InteruptHandler & other) const +{ + return isEqual(other); +} + +bool nx::InteruptHandler::operator!=(const InteruptHandler & other) const +{ + return !isEqual(other); +} + +void nx::InteruptHandler::operator=(const InteruptHandler & other) +{ + copyFrom(other); +} + +void nx::InteruptHandler::importKernelCapabilityList(const fnd::List& caps) +{ + // convert to interupts + fnd::List interupts; + for (size_t i = 0; i < caps.getSize(); i++) + { + interupts[i].setKernelCapability(caps[i]); + } + + mInterupts.clear(); + for (size_t i = 0; i < interupts.getSize(); i++) + { + // weird condition for first interupt + if (interupts[i][1] == 0 && i == 0) + { + mInterupts.addElement(interupts[i][0]); + continue; + } + + // we found a stub + if (interupts[i][1] == InteruptEntry::kInteruptMax && interupts[i][1] == InteruptEntry::kInteruptMax) + { + continue; + } + + // add interupts + mInterupts.hasElement(interupts[i][0]) == false ? mInterupts.addElement(interupts[i][0]) : throw fnd::Exception(kModuleName, "Interupt already added"); + mInterupts.hasElement(interupts[i][1]) == false ? mInterupts.addElement(interupts[i][1]) : throw fnd::Exception(kModuleName, "Interupt already added"); + } + + mIsSet = true; +} + +void nx::InteruptHandler::exportKernelCapabilityList(fnd::List& caps) const +{ + if (isSet() == false) + return; + + size_t i = 0; + if (mInterupts.getSize() % 2) + { + caps.addElement(InteruptEntry(mInterupts[i], 0).getKernelCapability()); + i++; + } + for (; i < mInterupts.getSize(); i += 2) + { + if (mInterupts[i] == InteruptEntry::kInteruptMax) + { + caps.addElement(InteruptEntry(InteruptEntry::kInteruptMax, InteruptEntry::kInteruptMax).getKernelCapability()); + } + caps.addElement(InteruptEntry(mInterupts[i], mInterupts[i+1]).getKernelCapability()); + if (mInterupts[i+1] == InteruptEntry::kInteruptMax) + { + caps.addElement(InteruptEntry(InteruptEntry::kInteruptMax, InteruptEntry::kInteruptMax).getKernelCapability()); + } + + } +} + +void nx::InteruptHandler::clear() +{ + mIsSet = false; + mInterupts.clear(); +} + +bool nx::InteruptHandler::isSet() const +{ + return mIsSet; +} + +const fnd::List& nx::InteruptHandler::getInterupts() const +{ + return mInterupts; +} + +void nx::InteruptHandler::setInterupts(const fnd::List& interupts) +{ + mInterupts.clear(); + for (size_t i = 0; i < interupts.getSize(); i++) + { + mInterupts.hasElement(interupts[i]) == false ? mInterupts.addElement(interupts[i]) : throw fnd::Exception(kModuleName, "Interupt already added"); + } + + mIsSet = true; +} + +void nx::InteruptHandler::copyFrom(const InteruptHandler & other) +{ + mIsSet = other.mIsSet; + mInterupts = other.mInterupts; +} + +bool nx::InteruptHandler::isEqual(const InteruptHandler & other) const +{ + return (mIsSet == other.mIsSet) \ + && (mInterupts == other.mInterupts); +} diff --git a/lib/nx/InteruptHandler.h b/lib/nx/InteruptHandler.h new file mode 100644 index 0000000..d4a8603 --- /dev/null +++ b/lib/nx/InteruptHandler.h @@ -0,0 +1,37 @@ +#pragma once +#include +#include + +namespace nx +{ + class InteruptHandler : + public IKernelCapabilityHandler + { + public: + InteruptHandler(); + + bool operator==(const InteruptHandler& other) const; + bool operator!=(const InteruptHandler& other) const; + void operator=(const InteruptHandler& other); + + // kernel capabilty list in/out + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; + void clear(); + bool isSet() const; + + // variables + const fnd::List& getInterupts() const; + void setInterupts(const fnd::List& interupts); + + private: + const std::string kModuleName = "INTERUPT_HANDLER"; + + bool mIsSet; + fnd::List mInterupts; + + void copyFrom(const InteruptHandler& other); + bool isEqual(const InteruptHandler& other) const; + }; +} + diff --git a/lib/nx/KcBinary.cpp b/lib/nx/KcBinary.cpp new file mode 100644 index 0000000..c4b9a69 --- /dev/null +++ b/lib/nx/KcBinary.cpp @@ -0,0 +1,252 @@ +#include "KcBinary.h" + + + +nx::KcBinary::KcBinary() +{} + +nx::KcBinary::KcBinary(const KcBinary & other) +{ + copyFrom(other); +} + +nx::KcBinary::KcBinary(const u8 * bytes, size_t len) +{ + importBinary(bytes, len); +} + +bool nx::KcBinary::operator==(const KcBinary & other) const +{ + return isEqual(other); +} + +bool nx::KcBinary::operator!=(const KcBinary & other) const +{ + return !isEqual(other); +} + +void nx::KcBinary::operator=(const KcBinary & other) +{ + copyFrom(other); +} + +const u8 * nx::KcBinary::getBytes() const +{ + return mBinaryBlob.getBytes(); +} + +size_t nx::KcBinary::getSize() const +{ + return mBinaryBlob.getSize(); +} + +void nx::KcBinary::exportBinary() +{ + fnd::List caps; + + // get kernel capabiliteis + mThreadInfo.exportKernelCapabilityList(caps); + mSystemCalls.exportKernelCapabilityList(caps); + mMemoryMap.exportKernelCapabilityList(caps); + mInterupts.exportKernelCapabilityList(caps); + mMiscParams.exportKernelCapabilityList(caps); + mKernelVersion.exportKernelCapabilityList(caps); + mHandleTableSize.exportKernelCapabilityList(caps); + mMiscFlags.exportKernelCapabilityList(caps); + + // allocate memory + mBinaryBlob.alloc(caps.getSize() * sizeof(u32)); + + // write to binary + u32* raw_caps = (u32*)mBinaryBlob.getBytes(); + for (size_t i = 0; i < caps.getSize(); i++) + { + raw_caps[i] = le_word(caps[i].getCap()); + } +} + +void nx::KcBinary::importBinary(const u8 * bytes) +{ + throw fnd::Exception(kModuleName, "Unsupported operation. importBinary(const u8* bytes) is not supported for variable size structures."); +} + +void nx::KcBinary::importBinary(const u8 * bytes, size_t len) +{ + if ((len % sizeof(u32)) != 0) + { + throw fnd::Exception(kModuleName, "KernelCapability list must be aligned to 4 bytes"); + } + + fnd::List threadInfoCaps; + fnd::List systemCallCaps; + fnd::List memoryMapCaps; + fnd::List interuptCaps; + fnd::List miscParamCaps; + fnd::List kernelVersionCaps; + fnd::List handleTableSizeCaps; + fnd::List miscFlagsCaps; + + const u32* raw_caps = (const u32*)bytes; + size_t cap_num = len / sizeof(u32); + KernelCapability cap; + for (size_t i = 0; i < cap_num; i++) + { + cap.setCap(le_word(raw_caps[i])); + switch (cap.getType()) + { + case (KernelCapability::KC_THREAD_INFO) : + threadInfoCaps.addElement(cap); + break; + case (KernelCapability::KC_ENABLE_SYSTEM_CALLS): + systemCallCaps.addElement(cap); + break; + case (KernelCapability::KC_MEMORY_MAP): + case (KernelCapability::KC_IO_MEMORY_MAP): + memoryMapCaps.addElement(cap); + break; + case (KernelCapability::KC_ENABLE_INTERUPTS): + interuptCaps.addElement(cap); + break; + case (KernelCapability::KC_MISC_PARAMS): + miscParamCaps.addElement(cap); + break; + case (KernelCapability::KC_KERNEL_VERSION): + kernelVersionCaps.addElement(cap); + break; + case (KernelCapability::KC_HANDLE_TABLE_SIZE): + handleTableSizeCaps.addElement(cap); + break; + case (KernelCapability::KC_MISC_FLAGS): + miscFlagsCaps.addElement(cap); + break; + default: + throw fnd::Exception(kModuleName, "Unsupported kernel capability type"); + } + } + + mThreadInfo.importKernelCapabilityList(threadInfoCaps); + mSystemCalls.importKernelCapabilityList(systemCallCaps); + mMemoryMap.importKernelCapabilityList(memoryMapCaps); + mInterupts.importKernelCapabilityList(interuptCaps); + mMiscParams.importKernelCapabilityList(memoryMapCaps); + mKernelVersion.importKernelCapabilityList(kernelVersionCaps); + mHandleTableSize.importKernelCapabilityList(handleTableSizeCaps); + mMiscFlags.importKernelCapabilityList(miscFlagsCaps); +} + +const nx::ThreadInfoHandler & nx::KcBinary::getThreadInfo() const +{ + return mThreadInfo; +} + +nx::ThreadInfoHandler & nx::KcBinary::getThreadInfo() +{ + return mThreadInfo; +} + +const nx::SystemCallHandler & nx::KcBinary::getSystemCalls() const +{ + return mSystemCalls; +} + +nx::SystemCallHandler & nx::KcBinary::getSystemCalls() +{ + return mSystemCalls; +} + +const nx::MemoryMappingHandler & nx::KcBinary::getMemoryMaps() const +{ + return mMemoryMap; +} + +nx::MemoryMappingHandler & nx::KcBinary::getMemoryMaps() +{ + return mMemoryMap; +} + +const nx::InteruptHandler & nx::KcBinary::getInterupts() const +{ + return mInterupts; +} + +nx::InteruptHandler & nx::KcBinary::getInterupts() +{ + return mInterupts; +} + +const nx::MiscParamsHandler & nx::KcBinary::getMiscParams() const +{ + return mMiscParams; +} + +nx::MiscParamsHandler & nx::KcBinary::getMiscParams() +{ + return mMiscParams; +} + +const nx::KernelVersionHandler & nx::KcBinary::getKernelVersion() const +{ + return mKernelVersion; +} + +nx::KernelVersionHandler & nx::KcBinary::getKernelVersion() +{ + return mKernelVersion; +} + +const nx::HandleTableSizeHandler & nx::KcBinary::getHandleTableSize() const +{ + return mHandleTableSize; +} + +nx::HandleTableSizeHandler & nx::KcBinary::getHandleTableSize() +{ + return mHandleTableSize; +} + +const nx::MiscFlagsHandler & nx::KcBinary::getMiscFlags() const +{ + return mMiscFlags; +} + +nx::MiscFlagsHandler & nx::KcBinary::getMiscFlags() +{ + return mMiscFlags; +} + +void nx::KcBinary::clearVariables() +{ + mBinaryBlob.clear(); + mThreadInfo.clear(); + mSystemCalls.clear(); + mMemoryMap.clear(); + mInterupts.clear(); + mMiscParams.clear(); + mKernelVersion.clear(); + mHandleTableSize.clear(); + mMiscFlags.clear(); +} + +bool nx::KcBinary::isEqual(const KcBinary & other) const +{ + return (mThreadInfo == other.mThreadInfo) \ + && (mSystemCalls == other.mSystemCalls) \ + && (mMemoryMap == other.mMemoryMap) \ + && (mInterupts == other.mInterupts) \ + && (mMiscParams == other.mMiscParams) \ + && (mKernelVersion == other.mKernelVersion) \ + && (mHandleTableSize == other.mHandleTableSize) \ + && (mMiscFlags == other.mMiscFlags); +} + +void nx::KcBinary::copyFrom(const KcBinary & other) +{ + mThreadInfo = other.mThreadInfo; + mSystemCalls = other.mSystemCalls; + mMemoryMap = other.mMemoryMap; + mInterupts = other.mInterupts; + mMiscParams = other.mMiscParams; + mKernelVersion = other.mKernelVersion; + mHandleTableSize = other.mHandleTableSize; + mMiscFlags = other.mMiscFlags; +} diff --git a/lib/nx/KcBinary.h b/lib/nx/KcBinary.h new file mode 100644 index 0000000..975b080 --- /dev/null +++ b/lib/nx/KcBinary.h @@ -0,0 +1,86 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace nx +{ + class KcBinary : + public ISerialiseableBinary + { + public: + KcBinary(); + KcBinary(const KcBinary& other); + KcBinary(const u8* bytes, size_t len); + + bool operator==(const KcBinary& other) const; + bool operator!=(const KcBinary& other) const; + void operator=(const KcBinary& other); + + // to be used after export + const u8* getBytes() const; + size_t getSize() const; + + // export/import binary + void exportBinary(); + void importBinary(const u8* bytes); + void importBinary(const u8* bytes, size_t len); + + // variables (consider further abstraction?) + const ThreadInfoHandler& getThreadInfo() const; + ThreadInfoHandler& getThreadInfo(); + + const SystemCallHandler& getSystemCalls() const; + SystemCallHandler& getSystemCalls(); + + const MemoryMappingHandler& getMemoryMaps() const; + MemoryMappingHandler& getMemoryMaps(); + + const InteruptHandler& getInterupts() const; + InteruptHandler& getInterupts(); + + const MiscParamsHandler& getMiscParams() const; + MiscParamsHandler& getMiscParams(); + + const KernelVersionHandler& getKernelVersion() const; + KernelVersionHandler& getKernelVersion(); + + const HandleTableSizeHandler& getHandleTableSize() const; + HandleTableSizeHandler& getHandleTableSize(); + + const MiscFlagsHandler& getMiscFlags() const; + MiscFlagsHandler& getMiscFlags(); + + private: + const std::string kModuleName = "KC_BINARY"; + + // raw binary + fnd::MemoryBlob mBinaryBlob; + + // variables + ThreadInfoHandler mThreadInfo; + SystemCallHandler mSystemCalls; + MemoryMappingHandler mMemoryMap; + InteruptHandler mInterupts; + MiscParamsHandler mMiscParams; + KernelVersionHandler mKernelVersion; + HandleTableSizeHandler mHandleTableSize; + MiscFlagsHandler mMiscFlags; + + + void clearVariables(); + bool isEqual(const KcBinary& other) const; + void copyFrom(const KcBinary& other); + }; +} + diff --git a/lib/nx/KernelVersionHandler.cpp b/lib/nx/KernelVersionHandler.cpp new file mode 100644 index 0000000..f312f5e --- /dev/null +++ b/lib/nx/KernelVersionHandler.cpp @@ -0,0 +1,92 @@ +#include "KernelVersionHandler.h" + + + +nx::KernelVersionHandler::KernelVersionHandler() : + mIsSet(false), + mEntry(0,0) +{} + +bool nx::KernelVersionHandler::operator==(const KernelVersionHandler & other) const +{ + return isEqual(other); +} + +bool nx::KernelVersionHandler::operator!=(const KernelVersionHandler & other) const +{ + return !isEqual(other); +} + +void nx::KernelVersionHandler::operator=(const KernelVersionHandler & other) +{ + copyFrom(other); +} + +void nx::KernelVersionHandler::importKernelCapabilityList(const fnd::List& caps) +{ + if (caps.getSize() > kMaxKernelCapNum) + { + throw fnd::Exception(kModuleName, "Too many kernel capabilities"); + } + + if (caps.getSize() == 0) + return; + + mEntry.setKernelCapability(caps[0]); + + mIsSet = true; +} + +void nx::KernelVersionHandler::exportKernelCapabilityList(fnd::List& caps) const +{ + if (isSet() == false) + return; + + caps.addElement(mEntry.getKernelCapability()); +} + +void nx::KernelVersionHandler::clear() +{ + mIsSet = false; + mEntry.setVerMajor(0); + mEntry.setVerMinor(0); +} + +bool nx::KernelVersionHandler::isSet() const +{ + return mIsSet; +} + +u16 nx::KernelVersionHandler::getVerMajor() const +{ + return mEntry.getVerMajor(); +} + +void nx::KernelVersionHandler::setVerMajor(u16 major) +{ + mEntry.setVerMajor(major); + mIsSet = true; +} + +u8 nx::KernelVersionHandler::getVerMinor() const +{ + return mEntry.getVerMinor(); +} + +void nx::KernelVersionHandler::setVerMinor(u8 minor) +{ + mEntry.setVerMinor(minor); + mIsSet = true; +} + +void nx::KernelVersionHandler::copyFrom(const KernelVersionHandler & other) +{ + mIsSet = other.mIsSet; + mEntry.setKernelCapability(other.mEntry.getKernelCapability()); +} + +bool nx::KernelVersionHandler::isEqual(const KernelVersionHandler & other) const +{ + return (mIsSet == other.mIsSet) \ + && (mEntry.getKernelCapability() == other.mEntry.getKernelCapability()); +} diff --git a/lib/nx/KernelVersionHandler.h b/lib/nx/KernelVersionHandler.h new file mode 100644 index 0000000..804d342 --- /dev/null +++ b/lib/nx/KernelVersionHandler.h @@ -0,0 +1,40 @@ +#pragma once +#include +#include + +namespace nx +{ + class KernelVersionHandler : + public IKernelCapabilityHandler + { + public: + KernelVersionHandler(); + + bool operator==(const KernelVersionHandler& other) const; + bool operator!=(const KernelVersionHandler& other) const; + void operator=(const KernelVersionHandler& other); + + // kernel capabilty list in/out + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; + void clear(); + bool isSet() const; + + // variables + u16 getVerMajor() const; + void setVerMajor(u16 major); + u8 getVerMinor() const; + void setVerMinor(u8 minor); + + private: + const std::string kModuleName = "KERNEL_VERSION_HANDLER"; + static const size_t kMaxKernelCapNum = 1; + + bool mIsSet; + KernelVersionEntry mEntry; + + void copyFrom(const KernelVersionHandler& other); + bool isEqual(const KernelVersionHandler& other) const; + }; +} + diff --git a/lib/nx/MemoryMappingHandler.cpp b/lib/nx/MemoryMappingHandler.cpp new file mode 100644 index 0000000..4cb802e --- /dev/null +++ b/lib/nx/MemoryMappingHandler.cpp @@ -0,0 +1,147 @@ +#include "MemoryMappingHandler.h" +#include "MemoryPageEntry.h" + + +nx::MemoryMappingHandler::MemoryMappingHandler() : + mIsSet(false) +{} + +bool nx::MemoryMappingHandler::operator==(const MemoryMappingHandler & other) const +{ + return isEqual(other); +} + +bool nx::MemoryMappingHandler::operator!=(const MemoryMappingHandler & other) const +{ + return !isEqual(other); +} + +void nx::MemoryMappingHandler::operator=(const MemoryMappingHandler & other) +{ + copyFrom(other); +} + +void nx::MemoryMappingHandler::importKernelCapabilityList(const fnd::List& caps) +{ + fnd::List entries; + + for (size_t i = 0; i < caps.getSize(); i++) + { + entries[i].setKernelCapability(caps[i]); + } + + mMemRange.clear(); + mMemPage.clear(); + for (size_t i = 0; i < entries.getSize();) + { + // has flag means "MemMap" + if (entries[i].isMultiplePages()) + { + // this entry is the last one or the next one isn't a memory map + if ((i + 1) == entries.getSize() || entries[i+1].isMultiplePages() == false) + { + throw fnd::Exception(kModuleName, "Illegal page address"); + } + + // check valid page address + if (entries[i].getPage() > kMaxPageAddr) + { + throw fnd::Exception(kModuleName, "Illegal page address"); + } + + // check valid page num + if (entries[i+1].getPage() > kMaxPageAddr) + { + throw fnd::Exception(kModuleName, "Illegal page num"); + } + + // add to list + mMemRange.addElement({ entries[i].getPage(), entries[i+1].getPage(), !entries[i].getFlag(), !entries[i+1].getFlag() }); + + // increment i by two + i += 2; + } + // otherwise means "IoMemMap" + else + { + // check valid page address + if (entries[i].getPage() > kMaxPageAddr) + { + throw fnd::Exception(kModuleName, "Illegal page address"); + } + + // add to list + mMemPage.addElement({ entries[i].getPage(), 1, true, true }); + + // increment i by one + i += 1; + } + } + + mIsSet = true; +} + +void nx::MemoryMappingHandler::exportKernelCapabilityList(fnd::List& caps) const +{ + if (isSet() == false) + return; + + MemoryPageEntry cap; + + // "mem maps" + cap.setMapMultiplePages(true); + for (size_t i = 0; i < mMemRange.getSize(); i++) + { + cap.setPage(mMemRange[i].addr & kMaxPageAddr); + cap.setFlag(!mMemRange[i].isRW); + caps.addElement(cap.getKernelCapability()); + + cap.setPage(mMemRange[i].size & kMaxPageNum); + cap.setFlag(!mMemRange[i].isIO); + caps.addElement(cap.getKernelCapability()); + } + + // "io maps" + cap.setMapMultiplePages(false); + for (size_t i = 0; i < mMemPage.getSize(); i++) + { + cap.setPage(mMemPage[i].addr & kMaxPageAddr); + caps.addElement(cap.getKernelCapability()); + } +} + +void nx::MemoryMappingHandler::clear() +{ + mIsSet = false; + mMemRange.clear(); + mMemPage.clear(); +} + +bool nx::MemoryMappingHandler::isSet() const +{ + return mIsSet; +} + +const fnd::List& nx::MemoryMappingHandler::getMemoryMaps() const +{ + return mMemRange; +} + +const fnd::List& nx::MemoryMappingHandler::getIoMemoryMaps() const +{ + return mMemPage; +} + +void nx::MemoryMappingHandler::copyFrom(const MemoryMappingHandler & other) +{ + mIsSet = other.mIsSet; + mMemRange = other.mMemRange; + mMemPage = other.mMemPage; +} + +bool nx::MemoryMappingHandler::isEqual(const MemoryMappingHandler & other) const +{ + return (mIsSet == other.mIsSet) \ + && (mMemRange == other.mMemRange) \ + && (mMemPage == other.mMemPage); +} diff --git a/lib/nx/MemoryMappingHandler.h b/lib/nx/MemoryMappingHandler.h new file mode 100644 index 0000000..c1992fe --- /dev/null +++ b/lib/nx/MemoryMappingHandler.h @@ -0,0 +1,69 @@ +#pragma once +#include + +namespace nx +{ + class MemoryMappingHandler : + public IKernelCapabilityHandler + { + public: + struct sMemoryMapping + { + u32 addr; // page index + u32 size; // page num + bool isRW; + bool isIO; + + bool operator==(const sMemoryMapping& other) const + { + return (addr == other.addr) \ + && (size == other.size) \ + && (isRW == other.isRW) \ + && (isIO == other.isIO); + } + + bool operator!=(const sMemoryMapping& other) const + { + return !operator==(other); + } + + const sMemoryMapping& operator=(const sMemoryMapping& other) + { + addr = other.addr; + size = other.size; + isRW = other.isRW; + isIO = other.isIO; + + return *this; + } + }; + + MemoryMappingHandler(); + + bool operator==(const MemoryMappingHandler& other) const; + bool operator!=(const MemoryMappingHandler& other) const; + void operator=(const MemoryMappingHandler& other); + + // kernel capabilty list in/out + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; + void clear(); + bool isSet() const; + + const fnd::List& getMemoryMaps() const; + const fnd::List& getIoMemoryMaps() const; + + private: + const std::string kModuleName = "MEMORY_MAPPING_HANDLER"; + static const u32 kMaxPageAddr = BIT(24) - 1; + static const u32 kMaxPageNum = BIT(20) - 1; + + bool mIsSet; + fnd::List mMemRange; + fnd::List mMemPage; + + void copyFrom(const MemoryMappingHandler& other); + bool isEqual(const MemoryMappingHandler& other) const; + }; +} + diff --git a/lib/nx/MemoryPageEntry.cpp b/lib/nx/MemoryPageEntry.cpp index 6a3b541..b005d0e 100644 --- a/lib/nx/MemoryPageEntry.cpp +++ b/lib/nx/MemoryPageEntry.cpp @@ -80,12 +80,12 @@ void nx::MemoryPageEntry::setFlag(bool flag) updateCapField(); } -bool nx::MemoryPageEntry::hasFlag() const +bool nx::MemoryPageEntry::isMultiplePages() const { return mUseFlag; } -void nx::MemoryPageEntry::useFlag(bool useFlag) +void nx::MemoryPageEntry::setMapMultiplePages(bool useFlag) { mUseFlag = useFlag; } diff --git a/lib/nx/MemoryPageEntry.h b/lib/nx/MemoryPageEntry.h index 378efbf..8e99ffc 100644 --- a/lib/nx/MemoryPageEntry.h +++ b/lib/nx/MemoryPageEntry.h @@ -23,8 +23,8 @@ namespace nx bool getFlag() const; void setFlag(bool flag); - bool hasFlag() const; - void useFlag(bool useFlag); + bool isMultiplePages() const; + void setMapMultiplePages(bool useFlag); private: const std::string kModuleName = "MEMORY_PAGE_ENTRY"; static const u32 kPageBits = 24; diff --git a/lib/nx/MiscFlagsEntry.h b/lib/nx/MiscFlagsEntry.h index 08c1c7e..0d541a6 100644 --- a/lib/nx/MiscFlagsEntry.h +++ b/lib/nx/MiscFlagsEntry.h @@ -8,26 +8,6 @@ namespace nx class MiscFlagsEntry { public: - // consider different definition location, perhaps in MiscFlagsHandler? - enum Flags - { - FLAG_ENABLE_DEBUG = BIT(0), - FLAG_FORCE_DEBUG = BIT(1), - FLAG_UNK02 = BIT(2), - FLAG_UNK03 = BIT(3), - FLAG_UNK04 = BIT(4), - FLAG_UNK05 = BIT(5), - FLAG_UNK06 = BIT(6), - FLAG_UNK07 = BIT(7), - FLAG_UNK08 = BIT(8), - FLAG_UNK09 = BIT(9), - FLAG_UNK10 = BIT(10), - FLAG_UNK11 = BIT(11), - FLAG_UNK12 = BIT(12), - FLAG_UNK13 = BIT(13), - FLAG_UNK14 = BIT(14), - }; - MiscFlagsEntry(); MiscFlagsEntry(const KernelCapability& kernel_cap); MiscFlagsEntry(u32 flags); diff --git a/lib/nx/MiscFlagsHandler.cpp b/lib/nx/MiscFlagsHandler.cpp new file mode 100644 index 0000000..9ad7a40 --- /dev/null +++ b/lib/nx/MiscFlagsHandler.cpp @@ -0,0 +1,64 @@ +#include "MiscFlagsHandler.h" + + + +nx::MiscFlagsHandler::MiscFlagsHandler() : + mIsSet(false) +{} + +void nx::MiscFlagsHandler::importKernelCapabilityList(const fnd::List& caps) +{ + if (caps.getSize() > kMaxKernelCapNum) + { + throw fnd::Exception(kModuleName, "Too many kernel capabilities"); + } + + if (caps.getSize() == 0) + return; + + mEntry.setKernelCapability(caps[0]); + + mIsSet = true; +} + +void nx::MiscFlagsHandler::exportKernelCapabilityList(fnd::List& caps) const +{ + if (isSet() == false) + return; + + caps.addElement(mEntry.getKernelCapability()); +} + +void nx::MiscFlagsHandler::clear() +{ + mIsSet = false; + mEntry.setFlags(0); +} + +bool nx::MiscFlagsHandler::isSet() const +{ + return mIsSet; +} + +u32 nx::MiscFlagsHandler::getFlags() const +{ + return mEntry.getFlags(); +} + +void nx::MiscFlagsHandler::setFlags(u32 flags) +{ + mEntry.setFlags(flags); + mIsSet = true; +} + +void nx::MiscFlagsHandler::copyFrom(const MiscFlagsHandler & other) +{ + mIsSet = other.mIsSet; + mEntry.setKernelCapability(other.mEntry.getKernelCapability()); +} + +bool nx::MiscFlagsHandler::isEqual(const MiscFlagsHandler & other) const +{ + return (mIsSet == other.mIsSet) \ + && (mEntry.getKernelCapability() == other.mEntry.getKernelCapability()); +} diff --git a/lib/nx/MiscFlagsHandler.h b/lib/nx/MiscFlagsHandler.h new file mode 100644 index 0000000..905f4cb --- /dev/null +++ b/lib/nx/MiscFlagsHandler.h @@ -0,0 +1,56 @@ +#pragma once +#include +#include + +namespace nx +{ + class MiscFlagsHandler : + public IKernelCapabilityHandler + { + public: + enum Flags + { + FLAG_ENABLE_DEBUG = BIT(0), + FLAG_FORCE_DEBUG = BIT(1), + FLAG_UNK02 = BIT(2), + FLAG_UNK03 = BIT(3), + FLAG_UNK04 = BIT(4), + FLAG_UNK05 = BIT(5), + FLAG_UNK06 = BIT(6), + FLAG_UNK07 = BIT(7), + FLAG_UNK08 = BIT(8), + FLAG_UNK09 = BIT(9), + FLAG_UNK10 = BIT(10), + FLAG_UNK11 = BIT(11), + FLAG_UNK12 = BIT(12), + FLAG_UNK13 = BIT(13), + FLAG_UNK14 = BIT(14), + }; + + MiscFlagsHandler(); + + bool operator==(const MiscFlagsHandler& other) const; + bool operator!=(const MiscFlagsHandler& other) const; + void operator=(const MiscFlagsHandler& other); + + // kernel capabilty list in/out + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; + void clear(); + bool isSet() const; + + // variables + u32 getFlags() const; + void setFlags(u32 flags); + private: + const std::string kModuleName = "MISC_FLAGS_HANDLER"; + static const size_t kMaxKernelCapNum = 1; + + bool mIsSet; + MiscFlagsEntry mEntry; + + void copyFrom(const MiscFlagsHandler& other); + bool isEqual(const MiscFlagsHandler& other) const; + }; + +} diff --git a/lib/nx/MiscParamsHandler.cpp b/lib/nx/MiscParamsHandler.cpp new file mode 100644 index 0000000..7f69909 --- /dev/null +++ b/lib/nx/MiscParamsHandler.cpp @@ -0,0 +1,80 @@ +#include "MiscParamsHandler.h" + + + +nx::MiscParamsHandler::MiscParamsHandler() : + mIsSet(false), + mEntry(0) +{} + +bool nx::MiscParamsHandler::operator==(const MiscParamsHandler & other) const +{ + return isEqual(other); +} + +bool nx::MiscParamsHandler::operator!=(const MiscParamsHandler & other) const +{ + return !isEqual(other); +} + +void nx::MiscParamsHandler::operator=(const MiscParamsHandler & other) +{ + copyFrom(other); +} + +void nx::MiscParamsHandler::importKernelCapabilityList(const fnd::List& caps) +{ + if (caps.getSize() > kMaxKernelCapNum) + { + throw fnd::Exception(kModuleName, "Too many kernel capabilities"); + } + + if (caps.getSize() == 0) + return; + + mEntry.setKernelCapability(caps[0]); + + mIsSet = true; +} + +void nx::MiscParamsHandler::exportKernelCapabilityList(fnd::List& caps) const +{ + if (isSet() == false) + return; + + caps.addElement(mEntry.getKernelCapability()); +} + +void nx::MiscParamsHandler::clear() +{ + mIsSet = false; + mEntry.setProgramType(0); +} + +bool nx::MiscParamsHandler::isSet() const +{ + return mIsSet; +} + +u8 nx::MiscParamsHandler::getProgramType() const +{ + return mEntry.getProgramType(); +} + +void nx::MiscParamsHandler::setProgramType(u8 type) +{ + mEntry.setProgramType(type); + mIsSet = true; +} + +void nx::MiscParamsHandler::copyFrom(const MiscParamsHandler & other) +{ + mIsSet = other.mIsSet; + mEntry.setKernelCapability(other.mEntry.getKernelCapability()); +} + +bool nx::MiscParamsHandler::isEqual(const MiscParamsHandler & other) const +{ + return (mIsSet == other.mIsSet) \ + && (mEntry.getKernelCapability() == other.mEntry.getKernelCapability()); +} diff --git a/lib/nx/MiscParamsHandler.h b/lib/nx/MiscParamsHandler.h new file mode 100644 index 0000000..357ac12 --- /dev/null +++ b/lib/nx/MiscParamsHandler.h @@ -0,0 +1,38 @@ +#pragma once +#include +#include + +namespace nx +{ + class MiscParamsHandler : + public IKernelCapabilityHandler + { + public: + MiscParamsHandler(); + + bool operator==(const MiscParamsHandler& other) const; + bool operator!=(const MiscParamsHandler& other) const; + void operator=(const MiscParamsHandler& other); + + // kernel capabilty list in/out + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; + void clear(); + bool isSet() const; + + // variables + u8 getProgramType() const; + void setProgramType(u8 type); + + private: + const std::string kModuleName = "MISC_PARAMS_HANDLER"; + static const size_t kMaxKernelCapNum = 1; + + bool mIsSet; + MiscParamsEntry mEntry; + + void copyFrom(const MiscParamsHandler& other); + bool isEqual(const MiscParamsHandler& other) const; + }; +} + diff --git a/lib/nx/NpdmFile.h b/lib/nx/NpdmFile.h new file mode 100644 index 0000000..8c44d3c --- /dev/null +++ b/lib/nx/NpdmFile.h @@ -0,0 +1,9 @@ +#pragma once + +// structure +// meta header +// alignment +// acid (aci desc sourced from base64 string) +// -> acid is prefaced by a signature then rsa key (both 2048 bit) +// alignment +// aci0 (aci generated in realtime) diff --git a/lib/nx/NpdmHeader.h b/lib/nx/NpdmHeader.h index bea9288..ecb622b 100644 --- a/lib/nx/NpdmHeader.h +++ b/lib/nx/NpdmHeader.h @@ -10,6 +10,7 @@ namespace nx public nx::ISerialiseableBinary { public: + // move these enums to NpdmBinary? enum InstructionType { INSTR_32BIT, @@ -100,15 +101,10 @@ namespace nx const std::string kNpdmStructSig = "META"; static const size_t kNameMaxLen = 0x10; static const size_t kProductCodeMaxLen = 0x10; - static const u8 kMaxPriority = 63; + static const u32 kMaxPriority = BIT(6) -1 ; static const size_t kNpdmAlignSize = 0x10; - enum FlagBits - { - IS_64BIT_INSTRUCTION_SET = BIT(0) - }; - #pragma pack (push, 1) struct sNpdmHeader { diff --git a/lib/nx/SystemCallHandler.cpp b/lib/nx/SystemCallHandler.cpp new file mode 100644 index 0000000..148d24e --- /dev/null +++ b/lib/nx/SystemCallHandler.cpp @@ -0,0 +1,123 @@ +#include "SystemCallHandler.h" +#include "SystemCallEntry.h" + + +nx::SystemCallHandler::SystemCallHandler() : + mIsSet(false), + mSystemCalls() +{} + +bool nx::SystemCallHandler::operator==(const SystemCallHandler & other) const +{ + return isEqual(other); +} + +bool nx::SystemCallHandler::operator!=(const SystemCallHandler & other) const +{ + return !isEqual(other); +} + +void nx::SystemCallHandler::operator=(const SystemCallHandler & other) +{ + copyFrom(other); +} + +void nx::SystemCallHandler::importKernelCapabilityList(const fnd::List& caps) +{ + SystemCallEntry entry; + + u8 syscallUpper, syscall; + for (size_t i = 0; i < caps.getSize(); i++) + { + entry.setKernelCapability(caps[i]); + + syscallUpper = 24 * entry.getSystemCallUpperBits(); + for (u8 j = 0; j < 24; j++) + { + syscall = syscallUpper + j; + + if (((entry.getSystemCallLowerBits() >> j) & 1) == 1) + { + mSystemCalls.hasElement(syscall) == false ? mSystemCalls.addElement(syscall) : throw fnd::Exception(kModuleName, "SystemCall already added"); + } + } + } + + + mIsSet = true; +} + +void nx::SystemCallHandler::exportKernelCapabilityList(fnd::List& caps) const +{ + if (isSet() == false) + return; + + fnd::List entries; + for (size_t i = 0; i < kSyscallTotalEntryNum; i++) + { + entries[i].setSystemCallUpperBits(i); + entries[i].setSystemCallLowerBits(0); + } + + for (size_t i = 0; i < mSystemCalls.getSize(); i++) + { + if (mSystemCalls[i] > kMaxSystemCall) + { + throw fnd::Exception(kModuleName, "Illegal SystemCall. (range: 0x00-0xBF inclusive)"); + } + + entries[mSystemCalls[i] / 24].setSystemCallLowerBits(entries[mSystemCalls[i] / 24].getSystemCallLowerBits() | BIT(mSystemCalls[i] % 24)); + } + + for (size_t i = 0; i < entries.getSize(); i++) + { + if (entries[i].getSystemCallLowerBits() != 0) + { + caps.addElement(entries[i].getKernelCapability()); + } + } +} + +void nx::SystemCallHandler::clear() +{ + mIsSet = false; + mSystemCalls.clear(); +} + +bool nx::SystemCallHandler::isSet() const +{ + return mIsSet; +} + +const fnd::List& nx::SystemCallHandler::getSystemCalls() const +{ + return mSystemCalls; +} + +void nx::SystemCallHandler::setSystemCalls(const fnd::List& calls) +{ + mSystemCalls.clear(); + for (size_t i = 0; i < calls.getSize(); i++) + { + if (mSystemCalls[i] > kMaxSystemCall) + { + throw fnd::Exception(kModuleName, "Illegal SystemCall. (range: 0x00-0xBF inclusive)"); + } + + mSystemCalls.hasElement(calls[i]) == false ? mSystemCalls.addElement(calls[i]) : throw fnd::Exception(kModuleName, "SystemCall already added"); + } + + mIsSet = true; +} + +void nx::SystemCallHandler::copyFrom(const SystemCallHandler & other) +{ + mIsSet = other.mIsSet; + mSystemCalls = other.mSystemCalls; +} + +bool nx::SystemCallHandler::isEqual(const SystemCallHandler & other) const +{ + return (mIsSet == other.mIsSet) \ + && (mSystemCalls == other.mSystemCalls); +} diff --git a/lib/nx/SystemCallHandler.h b/lib/nx/SystemCallHandler.h new file mode 100644 index 0000000..99f2861 --- /dev/null +++ b/lib/nx/SystemCallHandler.h @@ -0,0 +1,38 @@ +#pragma once +#include + +namespace nx +{ + class SystemCallHandler : + public IKernelCapabilityHandler + { + public: + SystemCallHandler(); + + bool operator==(const SystemCallHandler& other) const; + bool operator!=(const SystemCallHandler& other) const; + void operator=(const SystemCallHandler& other); + + // kernel capabilty list in/out + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; + void clear(); + bool isSet() const; + + // variables + const fnd::List& getSystemCalls() const; + void setSystemCalls(const fnd::List& calls); + + private: + const std::string kModuleName = "SYSTEM_CALL_HANDLER"; + static const u32 kMaxSystemCall = (BIT(3) * 24) - 1; + static const size_t kSyscallTotalEntryNum = (kMaxSystemCall / 24) + 1; + + bool mIsSet; + fnd::List mSystemCalls; + + void copyFrom(const SystemCallHandler& other); + bool isEqual(const SystemCallHandler& other) const; + }; + +} diff --git a/lib/nx/ThreadInfoHandler.cpp b/lib/nx/ThreadInfoHandler.cpp new file mode 100644 index 0000000..345397f --- /dev/null +++ b/lib/nx/ThreadInfoHandler.cpp @@ -0,0 +1,115 @@ +#include "ThreadInfoHandler.h" + + + +nx::ThreadInfoHandler::ThreadInfoHandler() : + mIsSet(false), + mEntry(0,0,0,0) +{} + +bool nx::ThreadInfoHandler::operator==(const ThreadInfoHandler & other) const +{ + return isEqual(other); +} + +bool nx::ThreadInfoHandler::operator!=(const ThreadInfoHandler & other) const +{ + return !isEqual(other); +} + +void nx::ThreadInfoHandler::operator=(const ThreadInfoHandler & other) +{ + copyFrom(other); +} + +void nx::ThreadInfoHandler::importKernelCapabilityList(const fnd::List& caps) +{ + if (caps.getSize() > kMaxKernelCapNum) + { + throw fnd::Exception(kModuleName, "Too many kernel capabilities"); + } + + if (caps.getSize() == 0) + return; + + mEntry.setKernelCapability(caps[0]); + mIsSet = true; +} + +void nx::ThreadInfoHandler::exportKernelCapabilityList(fnd::List& caps) const +{ + if (isSet() == false) + return; + + caps.addElement(mEntry.getKernelCapability()); +} + +void nx::ThreadInfoHandler::clear() +{ + mIsSet = false; + mEntry.setMaxPriority(0); + mEntry.setMinPriority(0); + mEntry.setMaxCoreNumber(0); + mEntry.setMinCoreNumber(0); +} + +bool nx::ThreadInfoHandler::isSet() const +{ + return mIsSet; +} + +u8 nx::ThreadInfoHandler::getMinPriority() const +{ + return mEntry.getMinPriority(); +} + +void nx::ThreadInfoHandler::setMinPriority(u8 priority) +{ + mEntry.setMinPriority(priority); + mIsSet = true; +} + +u8 nx::ThreadInfoHandler::getMaxPriority() const +{ + return mEntry.getMaxPriority(); +} + +void nx::ThreadInfoHandler::setMaxPriority(u8 priority) +{ + mEntry.setMaxPriority(priority); + mIsSet = true; +} + +u8 nx::ThreadInfoHandler::getMinCoreNumber() const +{ + return mEntry.getMinCoreNumber(); +} + +void nx::ThreadInfoHandler::setMinCoreNumber(u8 core_num) +{ + mEntry.setMinCoreNumber(core_num); + mIsSet = true; +} + +u8 nx::ThreadInfoHandler::getMaxCoreNumber() const +{ + return mEntry.getMaxCoreNumber(); +} + +void nx::ThreadInfoHandler::setMaxCoreNumber(u8 core_num) +{ + mEntry.setMaxCoreNumber(core_num); + mIsSet = true; +} + +void nx::ThreadInfoHandler::copyFrom(const ThreadInfoHandler & other) +{ + mIsSet = other.mIsSet; + mEntry.setKernelCapability(other.mEntry.getKernelCapability()); +} + +bool nx::ThreadInfoHandler::isEqual(const ThreadInfoHandler & other) const +{ + return (mIsSet == other.mIsSet) \ + && (mEntry.getKernelCapability() == other.mEntry.getKernelCapability()); +} diff --git a/lib/nx/ThreadInfoHandler.h b/lib/nx/ThreadInfoHandler.h new file mode 100644 index 0000000..c8381ae --- /dev/null +++ b/lib/nx/ThreadInfoHandler.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include + +namespace nx +{ + class ThreadInfoHandler : + public IKernelCapabilityHandler + { + public: + ThreadInfoHandler(); + + bool operator==(const ThreadInfoHandler& other) const; + bool operator!=(const ThreadInfoHandler& other) const; + void operator=(const ThreadInfoHandler& other); + + // kernel capabilty list in/out + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; + void clear(); + bool isSet() const; + + // variables + u8 getMinPriority() const; + void setMinPriority(u8 priority); + u8 getMaxPriority() const; + void setMaxPriority(u8 priority); + u8 getMinCoreNumber() const; + void setMinCoreNumber(u8 core_num); + u8 getMaxCoreNumber() const; + void setMaxCoreNumber(u8 core_num); + + private: + const std::string kModuleName = "THREAD_INFO_HANDLER"; + static const size_t kMaxKernelCapNum = 1; + + bool mIsSet; + ThreadInfoEntry mEntry; + + void copyFrom(const ThreadInfoHandler& other); + bool isEqual(const ThreadInfoHandler& other) const; + }; +} + diff --git a/lib/nx/nx.vcxproj b/lib/nx/nx.vcxproj index e54c4d9..4436711 100644 --- a/lib/nx/nx.vcxproj +++ b/lib/nx/nx.vcxproj @@ -23,39 +23,57 @@ + + + + + + + + + + + + + + + + + + 15.0 diff --git a/lib/nx/nx.vcxproj.filters b/lib/nx/nx.vcxproj.filters index 146d82e..8f4d49b 100644 --- a/lib/nx/nx.vcxproj.filters +++ b/lib/nx/nx.vcxproj.filters @@ -72,6 +72,33 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + @@ -122,5 +149,32 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + \ No newline at end of file