From 5de0a3972c4aced825a6cff3c4e2d929e0c5f842 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 4 Nov 2022 05:32:27 +0200 Subject: [PATCH] Added usermode process creation (currently broken) --- Execute/Parse.cpp | 32 +++++++++++++++++++- Execute/Spawn.cpp | 76 +++++++++++++++++++++++++++++++++++++++++++++-- KThread.cpp | 6 ++-- include/exec.hpp | 22 +++++++++++++- 4 files changed, 130 insertions(+), 6 deletions(-) diff --git a/Execute/Parse.cpp b/Execute/Parse.cpp index 1c91b312..3544ef5a 100644 --- a/Execute/Parse.cpp +++ b/Execute/Parse.cpp @@ -1,6 +1,36 @@ #include +#include "../kernel.h" +#include "../Fex.hpp" + namespace Execute { - + BinaryType GetBinaryType(char *Path) + { + BinaryType Type = BinaryType::BinTypeInvalid; + FileSystem::FILE *ExFile = vfs->Open(Path); + + if (ExFile->Status == FileSystem::FileStatus::OK) + { + if (ExFile->Node->Flags == FileSystem::NodeFlags::FS_FILE) + { + Fex *FexHdr = (Fex *)ExFile->Node->Address; + if (FexHdr->Magic[0] == 'F' && FexHdr->Magic[1] == 'E' && FexHdr->Magic[2] == 'X' && FexHdr->Magic[3] == '\0') + { + if (FexHdr->Type == FexFormatType::FexFormatType_Executable) + { + Type = BinaryType::BinTypeFex; + goto Exit; + } + } + + /* ... */ + + Type = BinaryType::BinTypeUnknown; + } + } + Exit: + vfs->Close(ExFile); + return Type; + } } diff --git a/Execute/Spawn.cpp b/Execute/Spawn.cpp index 4baf0621..61385343 100644 --- a/Execute/Spawn.cpp +++ b/Execute/Spawn.cpp @@ -1,9 +1,81 @@ #include +#include +#include +#include + +#include "../kernel.h" +#include "../Fex.hpp" + +using namespace Tasking; + namespace Execute { - ExStatus Spawn(char *Path, uint64_t Arg0, uint64_t Arg1) + SpawnData Spawn(char *Path, uint64_t Arg0, uint64_t Arg1) { - return ExStatus::Unknown; + SpawnData ret = {.Status = ExStatus::Unknown, + .Process = nullptr, + .Thread = nullptr}; + FileSystem::FILE *ExFile = vfs->Open(Path); + if (ExFile->Status == FileSystem::FileStatus::OK) + { + if (ExFile->Node->Flags == FileSystem::NodeFlags::FS_FILE) + { + BinaryType Type = GetBinaryType(Path); + switch (Type) + { + case BinaryType::BinTypeFex: + { + Fex *FexHdr = (Fex *)ExFile->Node->Address; + if (FexHdr->Magic[0] == 'F' && FexHdr->Magic[1] == 'E' && FexHdr->Magic[2] == 'X' && FexHdr->Magic[3] == '\0') + { + if (FexHdr->Type == FexFormatType::FexFormatType_Executable) + { + const char *BaseName; + cwk_path_get_basename(Path, &BaseName, nullptr); + PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User); + + void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile->Node->Length)); + memcpy(BaseImage, (void *)ExFile->Node->Address, ExFile->Node->Length); + + for (uint64_t i = 0; i < TO_PAGES(ExFile->Node->Length); i++) + Memory::Virtual(Process->PageTable).Map((void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), (void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::US); + + TCB *Thread = TaskManager->CreateThread(Process, + (IP)FexHdr->Pointer, + Arg0, Arg1, + (IPOffset)BaseImage, + TaskArchitecture::x64, + TaskCompatibility::Native); + ret.Process = Process; + ret.Thread = Thread; + ret.Status = ExStatus::OK; + goto Exit; + } + } + ret.Status = ExStatus::InvalidFileHeader; + goto Exit; + } + default: + ret.Status = ExStatus::Unsupported; + goto Exit; + } + goto Exit; + } + } + else if (ExFile->Status == FileSystem::FileStatus::NOT_FOUND) + { + ret.Status = ExStatus::InvalidFilePath; + goto Exit; + } + else + { + ret.Status = ExStatus::InvalidFile; + goto Exit; + } + + Exit: + vfs->Close(ExFile); + return ret; } } diff --git a/KThread.cpp b/KThread.cpp index 3d918aef..a10cb936 100644 --- a/KThread.cpp +++ b/KThread.cpp @@ -79,13 +79,15 @@ void KernelMainThread() argc = argv.size() - 1; // TODO: Untested! - Execute::ExStatus ret = Execute::Spawn(Config.InitPath, argc, (uint64_t)argv.data()); - if (ret != Execute::ExStatus::OK) + Execute::SpawnData ret = Execute::Spawn(Config.InitPath, argc, (uint64_t)argv.data()); + if (ret.Status != Execute::ExStatus::OK) { KPrint("\eE85230Failed to start %s! Code: %d", Config.InitPath, ret); CPU::Halt(true); } TaskManager->GetCurrentThread()->SetPriority(1); + TaskManager->WaitForThread(ret.Thread); + KPrint("\eE85230Userspace process exited with code %d", ret.Thread->GetExitCode()); CPU::Halt(true); } diff --git a/include/exec.hpp b/include/exec.hpp index b7a7d90f..118b3456 100644 --- a/include/exec.hpp +++ b/include/exec.hpp @@ -3,12 +3,24 @@ #include +#include + namespace Execute { + enum BinaryType + { + BinTypeInvalid, + BinTypeFex, + BinTypeElf, + BinTypePE, + BinTypeUnknown + }; + enum ExStatus { OK, Unknown, + Unsupported, InvalidFile, InvalidFileFormat, InvalidFileHeader, @@ -17,7 +29,15 @@ namespace Execute InvalidFilePath }; - ExStatus Spawn(char *Path, uint64_t Arg0, uint64_t Arg1); + struct SpawnData + { + ExStatus Status; + Tasking::PCB *Process; + Tasking::TCB *Thread; + }; + + BinaryType GetBinaryType(char *Path); + SpawnData Spawn(char *Path, uint64_t Arg0, uint64_t Arg1); } #endif // !__FENNIX_KERNEL_FILE_EXECUTE_H__