summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AK/Function.h1
-rw-r--r--ELFLoader/ExecSpace.cpp11
-rw-r--r--ELFLoader/ExecSpace.h3
-rw-r--r--Kernel/MemoryManager.cpp29
-rw-r--r--Kernel/MemoryManager.h2
-rw-r--r--Kernel/Task.cpp100
-rw-r--r--Kernel/Task.h3
-rw-r--r--Kernel/_fs_contentsbin1024000 -> 1024000 bytes
-rw-r--r--Kernel/init.cpp4
-rw-r--r--LibC/entry.cpp4
10 files changed, 141 insertions, 16 deletions
diff --git a/AK/Function.h b/AK/Function.h
index 0fef35abe8..34a2bc68fc 100644
--- a/AK/Function.h
+++ b/AK/Function.h
@@ -25,6 +25,7 @@
#pragma once
+#include "Assertions.h"
#include "OwnPtr.h"
#include "StdLib.h"
diff --git a/ELFLoader/ExecSpace.cpp b/ELFLoader/ExecSpace.cpp
index fb6d55a0dd..cbcc8568a5 100644
--- a/ELFLoader/ExecSpace.cpp
+++ b/ELFLoader/ExecSpace.cpp
@@ -22,7 +22,9 @@ int puts(const char* str)
void ExecSpace::initializeBuiltins()
{
+#ifndef SERENITY
m_symbols.set("puts", { (char*)puts, 0 });
+#endif
}
#ifdef SERENITY
@@ -86,8 +88,13 @@ char* ExecSpace::symbolPtr(const char* name)
char* ExecSpace::allocateArea(String&& name, unsigned size)
{
- char* ptr = static_cast<char*>(kmalloc(size));
- ASSERT(ptr);
+ char* ptr;
+ if (hookableAlloc)
+ ptr = static_cast<char*>(hookableAlloc(name, size));
+ else
+ ptr = static_cast<char*>(kmalloc(size));
+ if (size)
+ ASSERT(ptr);
m_areas.append(make<Area>(move(name), ptr, size));
return ptr;
}
diff --git a/ELFLoader/ExecSpace.h b/ELFLoader/ExecSpace.h
index 1e22468af4..432bf0a82e 100644
--- a/ELFLoader/ExecSpace.h
+++ b/ELFLoader/ExecSpace.h
@@ -1,5 +1,6 @@
#pragma once
+#include <AK/Function.h>
#include <AK/HashMap.h>
#include <AK/MappedFile.h>
#include <AK/OwnPtr.h>
@@ -37,6 +38,8 @@ public:
ExecSpace();
~ExecSpace();
+ Function<void*(const String&, size_t)> hookableAlloc;
+
#ifdef SERENITY
bool loadELF(ByteBuffer&&);
#else
diff --git a/Kernel/MemoryManager.cpp b/Kernel/MemoryManager.cpp
index 1d85aca254..019242a741 100644
--- a/Kernel/MemoryManager.cpp
+++ b/Kernel/MemoryManager.cpp
@@ -161,20 +161,27 @@ bool MemoryManager::unmapRegionsForTask(Task& task)
return true;
}
+bool MemoryManager::mapRegion(Task& task, Task::Region& region)
+{
+ auto& zone = *region.zone;
+ for (size_t i = 0; i < zone.m_pages.size(); ++i) {
+ auto laddr = region.linearAddress.offset(i * PAGE_SIZE);
+ auto pte = ensurePTE(laddr);
+ pte.setPhysicalPageBase(zone.m_pages[i].get());
+ pte.setPresent(true);
+ pte.setWritable(true);
+ pte.setUserAllowed(!task.isRing0());
+
+ //kprintf("MM: >> Mapped L%x => P%x <<\n", laddr, zone.m_pages[i].get());
+ }
+ return true;
+}
+
bool MemoryManager::mapRegionsForTask(Task& task)
{
for (auto& region : task.m_regions) {
- auto& zone = *region->zone;
- for (size_t i = 0; i < zone.m_pages.size(); ++i) {
- auto laddr = region->linearAddress.offset(i * PAGE_SIZE);
- auto pte = ensurePTE(laddr);
- pte.setPhysicalPageBase(zone.m_pages[i].get());
- pte.setPresent(true);
- pte.setWritable(true);
- pte.setUserAllowed(!task.isRing0());
-
- //kprintf("MM: >> Mapped L%x => P%x <<\n", laddr, zone.m_pages[i].get());
- }
+ if (!mapRegion(task, *region))
+ return false;
}
return true;
}
diff --git a/Kernel/MemoryManager.h b/Kernel/MemoryManager.h
index 7c6910a5da..a597280add 100644
--- a/Kernel/MemoryManager.h
+++ b/Kernel/MemoryManager.h
@@ -6,6 +6,7 @@
#include <AK/RetainPtr.h>
#include <AK/Vector.h>
#include <AK/HashMap.h>
+#include "Task.h"
class Task;
@@ -49,6 +50,7 @@ public:
// HACK: don't use this jeez :(
byte* quickMapOnePage(PhysicalAddress);
+ bool mapRegion(Task&, Task::Region&);
bool mapRegionsForTask(Task&);
bool unmapRegionsForTask(Task&);
diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp
index 96b5508564..cab2b17ea6 100644
--- a/Kernel/Task.cpp
+++ b/Kernel/Task.cpp
@@ -7,6 +7,7 @@
#include "system.h"
#include <VirtualFileSystem/FileHandle.h>
#include <VirtualFileSystem/VirtualFileSystem.h>
+#include <ELFLoader/ExecSpace.h>
#include "MemoryManager.h"
Task* current;
@@ -103,6 +104,104 @@ Task::Region* Task::allocateRegion(size_t size, String&& name)
return m_regions.last().ptr();
}
+Task* Task::create(const String& path, uid_t uid, gid_t gid)
+{
+ auto parts = path.split('/');
+ if (parts.isEmpty())
+ return nullptr;
+
+ auto handle = VirtualFileSystem::the().open(path);
+ if (!handle)
+ return nullptr;
+
+ auto elfData = handle->readEntireFile();
+ if (!elfData)
+ return nullptr;
+
+ Task* t = new Task(parts.takeLast(), uid, gid);
+
+ ExecSpace space;
+ space.hookableAlloc = [&] (const String& name, size_t size) {
+ if (!size)
+ return (void*)nullptr;
+ size = ((size / 4096) + 1) * 4096;
+ Region* region = t->allocateRegion(size, String(name));
+ ASSERT(region);
+ MemoryManager::the().mapRegion(*t, *region);
+ return (void*)region->linearAddress.asPtr();
+ };
+ bool success = space.loadELF(move(elfData));
+ if (!success) {
+ delete t;
+ return nullptr;
+ }
+
+ t->m_tss.eip = (dword)space.symbolPtr("_start");
+
+ // Add this task to head of task list (meaning it's next to run too, ATM.)
+ cli();
+ s_tasks->prepend(t);
+ system.nprocess++;
+ kprintf("Task %u (%s) spawned @ %p\n", t->pid(), t->name().characters(), t->m_tss.eip);
+ sti();
+
+ return t;
+}
+
+Task::Task(String&& name, uid_t uid, gid_t gid)
+ : m_name(move(name))
+ , m_pid(next_pid++)
+ , m_uid(uid)
+ , m_gid(gid)
+ , m_state(Runnable)
+ , m_ring(Ring3)
+{
+ m_nextRegion = LinearAddress(0x600000);
+
+ memset(&m_tss, 0, sizeof(m_tss));
+ memset(&m_ldtEntries, 0, sizeof(m_ldtEntries));
+
+ allocateLDT();
+
+ // Only IF is set when a task boots.
+ m_tss.eflags = 0x0202;
+
+ WORD codeSegment = 0x1b;
+ WORD dataSegment = 0x23;
+ WORD stackSegment = dataSegment;
+
+ m_tss.ds = dataSegment;
+ m_tss.es = dataSegment;
+ m_tss.fs = dataSegment;
+ m_tss.gs = dataSegment;
+ m_tss.ss = stackSegment;
+ m_tss.cs = codeSegment;
+
+ m_tss.cr3 = MemoryManager::the().pageDirectoryBase().get();
+
+ // NOTE: Each task gets 16KB of stack.
+ static const DWORD defaultStackSize = 16384;
+
+ auto* region = allocateRegion(defaultStackSize, "stack");
+ ASSERT(region);
+ m_stackTop = region->linearAddress.offset(defaultStackSize).get() & 0xfffffff8;
+ m_tss.esp = m_stackTop;
+
+ // Set up a separate stack for Ring0.
+ // FIXME: Don't leak this stack.
+ m_kernelStack = kmalloc(defaultStackSize);
+ DWORD ring0StackTop = ((DWORD)m_kernelStack + defaultStackSize) & 0xffffff8;
+ m_tss.ss0 = 0x10;
+ m_tss.esp0 = ring0StackTop;
+
+ // HACK: Ring2 SS in the TSS is the current PID.
+ m_tss.ss2 = m_pid;
+
+ m_farPtr.offset = 0x98765432;
+
+ ASSERT(m_pid);
+}
+
Task::Task(void (*e)(), const char* n, IPC::Handle h, RingLevel ring)
: m_name(n)
, m_entry(e)
@@ -241,7 +340,6 @@ void Task::sys$exit(int status)
kprintf("sys$exit: %s(%u) exit with status %d\n", name().characters(), pid(), status);
setState(Exiting);
- dumpRegions();
s_tasks->remove(this);
diff --git a/Kernel/Task.h b/Kernel/Task.h
index eaf338b212..2e230bf2ef 100644
--- a/Kernel/Task.h
+++ b/Kernel/Task.h
@@ -16,6 +16,9 @@ class Zone;
class Task : public InlineLinkedListNode<Task> {
friend class InlineLinkedListNode<Task>;
public:
+ static Task* create(const String& path, uid_t, gid_t);
+ Task(String&& name, uid_t, gid_t);
+
#ifdef TASK_SANITY_CHECKS
static void checkSanity(const char* msg = nullptr);
#else
diff --git a/Kernel/_fs_contents b/Kernel/_fs_contents
index fb6d9448f3..db5b3cfb2f 100644
--- a/Kernel/_fs_contents
+++ b/Kernel/_fs_contents
Binary files differ
diff --git a/Kernel/init.cpp b/Kernel/init.cpp
index 238f6d4253..b35f34bcb6 100644
--- a/Kernel/init.cpp
+++ b/Kernel/init.cpp
@@ -27,7 +27,7 @@
#include "Console.h"
#define TEST_VFS
-#define TEST_ELF_LOADER
+//#define TEST_ELF_LOADER
//#define TEST_CRASHY_USER_PROCESSES
static void motd_main() NORETURN;
@@ -167,6 +167,8 @@ static void init_stage2()
}
#endif
+ auto* idTask = Task::create("/bin/id", (uid_t)209, (gid_t)1985);
+
//new Task(motd_main, "motd", IPC::Handle::MotdTask, Task::Ring0);
//new Task(syscall_test_main, "syscall_test", IPC::Handle::MotdTask, Task::Ring3);
diff --git a/LibC/entry.cpp b/LibC/entry.cpp
index c84b819b02..9a34577977 100644
--- a/LibC/entry.cpp
+++ b/LibC/entry.cpp
@@ -5,7 +5,9 @@ extern "C" int main(int, char**);
extern "C" int _start()
{
// FIXME: Pass appropriate argc/argv.
- main(0, nullptr);
+ int status = main(0, nullptr);
+
+ Syscall::invoke(Syscall::PosixExit, status);
// Birger's birthday <3
return 20150614;