summaryrefslogtreecommitdiffhomepage
path: root/dev/Kernel/Sources/PEFCodeManager.cxx
diff options
context:
space:
mode:
authorAmlal EL Mahrouss <amlalelmahrouss@icloud.com>2024-08-15 18:35:34 +0200
committerAmlal EL Mahrouss <amlalelmahrouss@icloud.com>2024-08-15 18:35:34 +0200
commitf3d931aa7cfaf96baef8383b59a8938779541ee7 (patch)
treefdb9fc51badb3dbd03e46ab0766a49d9522e13e2 /dev/Kernel/Sources/PEFCodeManager.cxx
parent86640816e8b1d3595365f1fcc8a2a9e61fb40ff1 (diff)
[IMP] Moved source code into dev/ folder.
Signed-off-by: Amlal EL Mahrouss <amlalelmahrouss@icloud.com>
Diffstat (limited to 'dev/Kernel/Sources/PEFCodeManager.cxx')
-rw-r--r--dev/Kernel/Sources/PEFCodeManager.cxx241
1 files changed, 241 insertions, 0 deletions
diff --git a/dev/Kernel/Sources/PEFCodeManager.cxx b/dev/Kernel/Sources/PEFCodeManager.cxx
new file mode 100644
index 00000000..d557cc2f
--- /dev/null
+++ b/dev/Kernel/Sources/PEFCodeManager.cxx
@@ -0,0 +1,241 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <KernelKit/DebugOutput.hxx>
+#include <KernelKit/Heap.hxx>
+#include <KernelKit/PEFCodeManager.hxx>
+#include <KernelKit/ProcessScheduler.hxx>
+#include <NewKit/Defines.hxx>
+#include <NewKit/KernelCheck.hxx>
+#include <NewKit/OwnPtr.hxx>
+#include <NewKit/String.hxx>
+
+namespace Kernel
+{
+ namespace Detail
+ {
+ /// @brief Get the PEF platform signature according to the compiled backebnd
+ UInt32 rt_get_pef_platform(void) noexcept
+ {
+#ifdef __NEWOS_32X0__
+ return kPefArch32x0;
+#elif defined(__NEWOS_64X0__)
+ return kPefArch64x0;
+#elif defined(__NEWOS_AMD64__)
+ return kPefArchAMD64;
+#elif defined(__NEWOS_PPC64__)
+ return kPefArchPowerPC;
+#elif defined(__NEWOS_ARM64__)
+ return kPefArchARM64;
+#else
+ return kPefArchInvalid;
+#endif // __32x0__ || __64x0__ || __x86_64__
+ }
+ } // namespace Detail
+
+ /// @brief PEF loader constructor w/ blob.
+ /// @param blob
+ PEFLoader::PEFLoader(const VoidPtr blob)
+ : fCachedBlob(blob)
+ {
+ MUST_PASS(fCachedBlob);
+ fBad = false;
+ }
+
+ /// @brief PEF loader constructor.
+ /// @param path the filesystem path.
+ PEFLoader::PEFLoader(const Char* path)
+ : fCachedBlob(nullptr), fBad(false), fFatBinary(false)
+ {
+ fFile.New(const_cast<Char*>(path), cRestrictRB);
+
+ if (StringBuilder::Equals(fFile->MIME(), this->MIME()))
+ {
+ fPath = StringBuilder::Construct(path).Leak();
+
+ auto cPefHeader = "PEFContainer";
+
+ fCachedBlob = fFile->Read(cPefHeader);
+
+ PEFContainer* container = reinterpret_cast<PEFContainer*>(fCachedBlob);
+
+ if (container->Cpu == Detail::rt_get_pef_platform() &&
+ container->Magic[0] == kPefMagic[0] &&
+ container->Magic[1] == kPefMagic[1] &&
+ container->Magic[2] == kPefMagic[2] &&
+ container->Magic[3] == kPefMagic[3] &&
+ container->Magic[4] == kPefMagic[4] && container->Abi == kPefAbi)
+ {
+ return;
+ }
+ else if (container->Magic[4] == kPefMagic[0] &&
+ container->Magic[3] == kPefMagic[1] &&
+ container->Magic[2] == kPefMagic[2] &&
+ container->Magic[1] == kPefMagic[3] &&
+ container->Magic[0] == kPefMagic[0] && container->Abi == kPefAbi)
+ {
+ /// This is a fat binary.
+ this->fFatBinary = true;
+ return;
+ }
+
+ kcout << "CodeManager: Warning: Executable format error!\n";
+ fBad = true;
+
+ mm_delete_ke_heap(fCachedBlob);
+
+ fCachedBlob = nullptr;
+ }
+ }
+
+ /// @brief PEF destructor.
+ PEFLoader::~PEFLoader()
+ {
+ if (fCachedBlob)
+ mm_delete_ke_heap(fCachedBlob);
+
+ fFile.Delete();
+ }
+
+ VoidPtr PEFLoader::FindSymbol(const char* name, Int32 kind)
+ {
+ if (!fCachedBlob || fBad)
+ return nullptr;
+
+ PEFContainer* container = reinterpret_cast<PEFContainer*>(fCachedBlob);
+
+ StringView cPefHeaderStr = StringBuilder::Construct("PEFContainerHeader:").Leak().Leak();
+ cPefHeaderStr += name;
+
+ auto blob = fFile->Read(cPefHeaderStr.CData());
+
+ PEFCommandHeader* container_header = reinterpret_cast<PEFCommandHeader*>(blob);
+
+ constexpr auto cMangleCharacter = '$';
+ const char* cContainerKinds[] = {".code64", ".data64", ".zero64", nullptr};
+
+ ErrorOr<StringView> errOrSym;
+
+ switch (kind)
+ {
+ case kPefCode: {
+ errOrSym = StringBuilder::Construct(cContainerKinds[0]); // code symbol.
+ break;
+ }
+ case kPefData: {
+ errOrSym = StringBuilder::Construct(cContainerKinds[1]); // data symbol.
+ break;
+ }
+ case kPefZero: {
+ errOrSym = StringBuilder::Construct(cContainerKinds[2]); // block starting symbol.
+ break;
+ }
+ default:
+ return nullptr;
+ }
+
+ char* unconstSymbol = const_cast<char*>(name);
+
+ for (SizeT i = 0UL; i < rt_string_len(unconstSymbol, kPefNameLen); ++i)
+ {
+ if (unconstSymbol[i] == ' ')
+ {
+ unconstSymbol[i] = cMangleCharacter;
+ }
+ }
+
+ errOrSym.Leak().Leak() += name;
+
+ for (SizeT index = 0; index < container->Count; ++index)
+ {
+ if (StringBuilder::Equals(container_header->Name,
+ errOrSym.Leak().Leak().CData()))
+ {
+ if (container_header->Kind == kind)
+ {
+ if (container_header->Cpu != Detail::rt_get_pef_platform())
+ {
+ if (!this->fFatBinary)
+ {
+ mm_delete_ke_heap(blob);
+ return nullptr;
+ }
+ }
+
+ Char* blobRet = new Char[container_header->Size];
+
+ rt_copy_memory((VoidPtr)((Char*)blob + sizeof(PEFCommandHeader)), blobRet, container_header->Size);
+
+ mm_delete_ke_heap(blob);
+ return blobRet;
+ }
+ }
+ }
+
+ mm_delete_ke_heap(blob);
+ return nullptr;
+ }
+
+ /// @brief Finds the executable entrypoint.
+ /// @return
+ ErrorOr<VoidPtr> PEFLoader::FindStart()
+ {
+ if (auto sym = this->FindSymbol(kPefStart, kPefCode); sym)
+ return ErrorOr<VoidPtr>(sym);
+
+ return ErrorOr<VoidPtr>(kErrorExecutable);
+ }
+
+ /// @brief Tells if the executable is loaded or not.
+ /// @return
+ bool PEFLoader::IsLoaded() noexcept
+ {
+ return !fBad && fCachedBlob;
+ }
+
+ namespace Utils
+ {
+ bool execute_from_image(PEFLoader& exec, const Int32& procKind) noexcept
+ {
+ auto errOrStart = exec.FindStart();
+
+ if (errOrStart.Error() != 0)
+ return false;
+
+ PROCESS_HEADER_BLOCK proc(errOrStart.Leak().Leak());
+ Ref<PROCESS_HEADER_BLOCK> refProc = proc;
+
+ proc.Kind = procKind;
+
+ return ProcessScheduler::The().Leak().Add(refProc);
+ }
+ } // namespace Utils
+
+ const char* PEFLoader::Path()
+ {
+ return fPath.Leak().CData();
+ }
+
+ const char* PEFLoader::AsString()
+ {
+#ifdef __32x0__
+ return "32x0 PEF format.";
+#elif defined(__64x0__)
+ return "64x0 PEF format.";
+#elif defined(__x86_64__)
+ return "x86_64 PEF format.";
+#elif defined(__powerpc64__)
+ return "POWER PEF format.";
+#else
+ return "Unknown PEF format.";
+#endif // __32x0__ || __64x0__ || __x86_64__ || __powerpc64__
+ }
+
+ const char* PEFLoader::MIME()
+ {
+ return kPefApplicationMime;
+ }
+} // namespace Kernel