mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 05:58:11 +00:00
Lots of hacking:
- Turn Keyboard into a CharacterDevice (85,1) at /dev/keyboard. - Implement MM::unmapRegionsForTask() and MM::unmapRegion() - Save SS correctly on interrupt. - Add a simple Spawn syscall for launching another process. - Move a bunch of IO syscall debug output behind DEBUG_IO. - Have ASSERT do a "cli" immediately when failing. This makes the output look proper every time. - Implement a bunch of syscalls in LibC. - Add a simple shell ("sh"). All it can do now is read a line of text from /dev/keyboard and then try launching the specified executable by calling spawn(). There are definitely bugs in here, but we're moving on forward.
This commit is contained in:
parent
72514c8b97
commit
fe237ee215
29 changed files with 276 additions and 32 deletions
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Assertions.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
#include "kstdio.h"
|
|
||||||
|
|
||||||
namespace AK {
|
namespace AK {
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ void Keyboard::handleIRQ()
|
||||||
case 0x9D: m_modifiers &= ~MOD_CTRL; break;
|
case 0x9D: m_modifiers &= ~MOD_CTRL; break;
|
||||||
case 0x2A: m_modifiers |= MOD_SHIFT; break;
|
case 0x2A: m_modifiers |= MOD_SHIFT; break;
|
||||||
case 0xAA: m_modifiers &= ~MOD_SHIFT; break;
|
case 0xAA: m_modifiers &= ~MOD_SHIFT; break;
|
||||||
case 0x1C: /* enter */ kprintf("\n"); break;
|
case 0x1C: /* enter */ m_queue.enqueue('\n'); break;
|
||||||
case 0xFA: /* i8042 ack */ break;
|
case 0xFA: /* i8042 ack */ break;
|
||||||
default:
|
default:
|
||||||
if (ch & 0x80) {
|
if (ch & 0x80) {
|
||||||
|
@ -55,11 +55,14 @@ void Keyboard::handleIRQ()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!m_modifiers)
|
if (!m_modifiers)
|
||||||
kprintf("%c", map[ch]);
|
m_queue.enqueue(map[ch]);
|
||||||
else if (m_modifiers & MOD_SHIFT)
|
else if (m_modifiers & MOD_SHIFT)
|
||||||
kprintf("%c", shift_map[ch]);
|
m_queue.enqueue(shift_map[ch]);
|
||||||
else if (m_modifiers & MOD_CTRL)
|
else if (m_modifiers & MOD_CTRL) {
|
||||||
kprintf("^%c", shift_map[ch]);
|
// FIXME: This is obviously not a good enough way to process ctrl+whatever.
|
||||||
|
m_queue.enqueue('^');
|
||||||
|
m_queue.enqueue(shift_map[ch]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//break;
|
//break;
|
||||||
}
|
}
|
||||||
|
@ -81,3 +84,18 @@ Keyboard::~Keyboard()
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t Keyboard::read(byte* buffer, size_t size)
|
||||||
|
{
|
||||||
|
ssize_t nread = 0;
|
||||||
|
while (nread < size) {
|
||||||
|
if (m_queue.isEmpty())
|
||||||
|
break;
|
||||||
|
buffer[nread++] = m_queue.dequeue();
|
||||||
|
}
|
||||||
|
return nread;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t Keyboard::write(const byte* data, size_t size)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -1,16 +1,25 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
#include <AK/DoublyLinkedList.h>
|
||||||
|
#include <AK/CircularQueue.h>
|
||||||
|
#include <VirtualFileSystem/CharacterDevice.h>
|
||||||
#include "IRQHandler.h"
|
#include "IRQHandler.h"
|
||||||
|
|
||||||
class Keyboard final : public IRQHandler {
|
class Keyboard final : public IRQHandler, public CharacterDevice {
|
||||||
public:
|
public:
|
||||||
virtual ~Keyboard() override;
|
virtual ~Keyboard() override;
|
||||||
Keyboard();
|
Keyboard();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// ^IRQHandler
|
||||||
virtual void handleIRQ() override;
|
virtual void handleIRQ() override;
|
||||||
|
|
||||||
|
// ^CharacterDevice
|
||||||
|
virtual ssize_t read(byte* buffer, size_t) override;
|
||||||
|
virtual ssize_t write(const byte* buffer, size_t) override;
|
||||||
|
|
||||||
|
CircularQueue<byte, 16> m_queue;
|
||||||
byte m_modifiers { 0 };
|
byte m_modifiers { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -156,8 +156,28 @@ byte* MemoryManager::quickMapOnePage(PhysicalAddress physicalAddress)
|
||||||
return (byte*)(4 * MB);
|
return (byte*)(4 * MB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MemoryManager::unmapRegion(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(0);
|
||||||
|
pte.setPresent(false);
|
||||||
|
pte.setWritable(false);
|
||||||
|
pte.setUserAllowed(false);
|
||||||
|
|
||||||
|
// kprintf("MM: >> Unmapped L%x => P%x <<\n", laddr, zone.m_pages[i].get());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool MemoryManager::unmapRegionsForTask(Task& task)
|
bool MemoryManager::unmapRegionsForTask(Task& task)
|
||||||
{
|
{
|
||||||
|
for (auto& region : task.m_regions) {
|
||||||
|
if (!unmapRegion(task, *region))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ public:
|
||||||
byte* quickMapOnePage(PhysicalAddress);
|
byte* quickMapOnePage(PhysicalAddress);
|
||||||
|
|
||||||
bool mapRegion(Task&, Task::Region&);
|
bool mapRegion(Task&, Task::Region&);
|
||||||
|
bool unmapRegion(Task&, Task::Region&);
|
||||||
bool mapRegionsForTask(Task&);
|
bool mapRegionsForTask(Task&);
|
||||||
bool unmapRegionsForTask(Task&);
|
bool unmapRegionsForTask(Task&);
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ asm(
|
||||||
" pushw %ss\n"
|
" pushw %ss\n"
|
||||||
" pushw %ss\n"
|
" pushw %ss\n"
|
||||||
" pushw %ss\n"
|
" pushw %ss\n"
|
||||||
|
" pushw %ss\n"
|
||||||
" popw %ds\n"
|
" popw %ds\n"
|
||||||
" popw %es\n"
|
" popw %es\n"
|
||||||
" popw %fs\n"
|
" popw %fs\n"
|
||||||
|
@ -29,6 +30,7 @@ asm(
|
||||||
" mov %esp, syscallRegDump\n"
|
" mov %esp, syscallRegDump\n"
|
||||||
" call syscall_entry\n"
|
" call syscall_entry\n"
|
||||||
" popw %gs\n"
|
" popw %gs\n"
|
||||||
|
" popw %gs\n"
|
||||||
" popw %fs\n"
|
" popw %fs\n"
|
||||||
" popw %es\n"
|
" popw %es\n"
|
||||||
" popw %ds\n"
|
" popw %ds\n"
|
||||||
|
@ -58,15 +60,16 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3)
|
||||||
//kprintf("syscall: sleep(%d)\n", arg1);
|
//kprintf("syscall: sleep(%d)\n", arg1);
|
||||||
current->sys$sleep(arg1);
|
current->sys$sleep(arg1);
|
||||||
break;
|
break;
|
||||||
|
case Syscall::Spawn:
|
||||||
|
return current->sys$spawn((const char*)arg1);
|
||||||
case Syscall::PosixOpen:
|
case Syscall::PosixOpen:
|
||||||
Task::checkSanity("syscall");
|
//kprintf("syscall: open('%s', %u)\n", arg1, arg2);
|
||||||
kprintf("syscall: open('%s', %u)\n", arg1, arg2);
|
|
||||||
return current->sys$open((const char*)arg1, (size_t)arg2);
|
return current->sys$open((const char*)arg1, (size_t)arg2);
|
||||||
case Syscall::PosixClose:
|
case Syscall::PosixClose:
|
||||||
kprintf("syscall: close(%d)\n", arg1);
|
//kprintf("syscall: close(%d)\n", arg1);
|
||||||
return current->sys$close((int)arg1);
|
return current->sys$close((int)arg1);
|
||||||
case Syscall::PosixRead:
|
case Syscall::PosixRead:
|
||||||
kprintf("syscall: read(%d, %p, %u)\n", arg1, arg2, arg3);
|
//kprintf("syscall: read(%d, %p, %u)\n", arg1, arg2, arg3);
|
||||||
return current->sys$read((int)arg1, (void*)arg2, (size_t)arg3);
|
return current->sys$read((int)arg1, (void*)arg2, (size_t)arg3);
|
||||||
case Syscall::PosixSeek:
|
case Syscall::PosixSeek:
|
||||||
// FIXME: This has the wrong signature, should be like lseek()
|
// FIXME: This has the wrong signature, should be like lseek()
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
namespace Syscall {
|
namespace Syscall {
|
||||||
|
|
||||||
enum Function {
|
enum Function {
|
||||||
|
Spawn = 0x1981,
|
||||||
Sleep = 0x1982,
|
Sleep = 0x1982,
|
||||||
Yield = 0x1983,
|
Yield = 0x1983,
|
||||||
PutCharacter = 1984,
|
PutCharacter = 1984,
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include <ELFLoader/ExecSpace.h>
|
#include <ELFLoader/ExecSpace.h>
|
||||||
#include "MemoryManager.h"
|
#include "MemoryManager.h"
|
||||||
|
|
||||||
|
//#define DEBUG_IO
|
||||||
|
|
||||||
Task* current;
|
Task* current;
|
||||||
Task* s_kernelTask;
|
Task* s_kernelTask;
|
||||||
|
|
||||||
|
@ -104,6 +106,14 @@ Task::Region* Task::allocateRegion(size_t size, String&& name)
|
||||||
return m_regions.last().ptr();
|
return m_regions.last().ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Task::sys$spawn(const char* path)
|
||||||
|
{
|
||||||
|
auto* child = Task::create(path, m_uid, m_gid);
|
||||||
|
if (child)
|
||||||
|
return child->pid();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
Task* Task::create(const String& path, uid_t uid, gid_t gid)
|
Task* Task::create(const String& path, uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
auto parts = path.split('/');
|
auto parts = path.split('/');
|
||||||
|
@ -118,6 +128,7 @@ Task* Task::create(const String& path, uid_t uid, gid_t gid)
|
||||||
if (!elfData)
|
if (!elfData)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
cli();
|
||||||
Task* t = new Task(parts.takeLast(), uid, gid);
|
Task* t = new Task(parts.takeLast(), uid, gid);
|
||||||
|
|
||||||
ExecSpace space;
|
ExecSpace space;
|
||||||
|
@ -137,9 +148,14 @@ Task* Task::create(const String& path, uid_t uid, gid_t gid)
|
||||||
}
|
}
|
||||||
|
|
||||||
t->m_tss.eip = (dword)space.symbolPtr("_start");
|
t->m_tss.eip = (dword)space.symbolPtr("_start");
|
||||||
|
if (!t->m_tss.eip) {
|
||||||
|
delete t;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryManager::the().unmapRegionsForTask(*t);
|
||||||
|
MemoryManager::the().mapRegionsForTask(*current);
|
||||||
|
|
||||||
// Add this task to head of task list (meaning it's next to run too, ATM.)
|
|
||||||
cli();
|
|
||||||
s_tasks->prepend(t);
|
s_tasks->prepend(t);
|
||||||
system.nprocess++;
|
system.nprocess++;
|
||||||
kprintf("Task %u (%s) spawned @ %p\n", t->pid(), t->name().characters(), t->m_tss.eip);
|
kprintf("Task %u (%s) spawned @ %p\n", t->pid(), t->name().characters(), t->m_tss.eip);
|
||||||
|
@ -357,10 +373,12 @@ void Task::taskDidCrash(Task* crashedTask)
|
||||||
{
|
{
|
||||||
// NOTE: This is called from an excepton handler, so interrupts are disabled.
|
// NOTE: This is called from an excepton handler, so interrupts are disabled.
|
||||||
crashedTask->setState(Crashing);
|
crashedTask->setState(Crashing);
|
||||||
crashedTask->dumpRegions();
|
// crashedTask->dumpRegions();
|
||||||
|
|
||||||
s_tasks->remove(crashedTask);
|
s_tasks->remove(crashedTask);
|
||||||
|
|
||||||
|
MemoryManager::the().unmapRegionsForTask(*crashedTask);
|
||||||
|
|
||||||
if (!scheduleNewTask()) {
|
if (!scheduleNewTask()) {
|
||||||
kprintf("Task::taskDidCrash: Failed to schedule a new task :(\n");
|
kprintf("Task::taskDidCrash: Failed to schedule a new task :(\n");
|
||||||
HANG;
|
HANG;
|
||||||
|
@ -491,7 +509,16 @@ static bool contextSwitch(Task* t)
|
||||||
// Some sanity checking to force a crash earlier.
|
// Some sanity checking to force a crash earlier.
|
||||||
auto csRPL = t->tss().cs & 3;
|
auto csRPL = t->tss().cs & 3;
|
||||||
auto ssRPL = t->tss().ss & 3;
|
auto ssRPL = t->tss().ss & 3;
|
||||||
ASSERT(csRPL == ssRPL);
|
|
||||||
|
if (csRPL != ssRPL) {
|
||||||
|
kprintf("Fuckup! Switching from %s(%u) to %s(%u) has RPL mismatch\n",
|
||||||
|
current->name().characters(), current->pid(),
|
||||||
|
t->name().characters(), t->pid()
|
||||||
|
);
|
||||||
|
kprintf("code: %w:%x\n", t->tss().cs, t->tss().eip);
|
||||||
|
kprintf(" stk: %w:%x\n", t->tss().ss, t->tss().esp);
|
||||||
|
ASSERT(csRPL == ssRPL);
|
||||||
|
}
|
||||||
|
|
||||||
if (current) {
|
if (current) {
|
||||||
// If the last task hasn't blocked (still marked as running),
|
// If the last task hasn't blocked (still marked as running),
|
||||||
|
@ -572,17 +599,24 @@ int Task::sys$seek(int fd, int offset)
|
||||||
ssize_t Task::sys$read(int fd, void* outbuf, size_t nread)
|
ssize_t Task::sys$read(int fd, void* outbuf, size_t nread)
|
||||||
{
|
{
|
||||||
Task::checkSanity("Task::sys$read");
|
Task::checkSanity("Task::sys$read");
|
||||||
|
#ifdef DEBUG_IO
|
||||||
kprintf("Task::sys$read: called(%d, %p, %u)\n", fd, outbuf, nread);
|
kprintf("Task::sys$read: called(%d, %p, %u)\n", fd, outbuf, nread);
|
||||||
|
#endif
|
||||||
auto* handle = fileHandleIfExists(fd);
|
auto* handle = fileHandleIfExists(fd);
|
||||||
|
#ifdef DEBUG_IO
|
||||||
kprintf("Task::sys$read: handle=%p\n", handle);
|
kprintf("Task::sys$read: handle=%p\n", handle);
|
||||||
|
#endif
|
||||||
if (!handle) {
|
if (!handle) {
|
||||||
kprintf("Task::sys$read: handle not found :(\n");
|
kprintf("Task::sys$read: handle not found :(\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG_IO
|
||||||
kprintf("call read on handle=%p\n", handle);
|
kprintf("call read on handle=%p\n", handle);
|
||||||
|
#endif
|
||||||
nread = handle->read((byte*)outbuf, nread);
|
nread = handle->read((byte*)outbuf, nread);
|
||||||
kprintf("called read\n");
|
#ifdef DEBUG_IO
|
||||||
kprintf("Task::sys$read: nread=%u\n", nread);
|
kprintf("Task::sys$read: nread=%u\n", nread);
|
||||||
|
#endif
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,7 +632,9 @@ int Task::sys$close(int fd)
|
||||||
int Task::sys$open(const char* path, size_t pathLength)
|
int Task::sys$open(const char* path, size_t pathLength)
|
||||||
{
|
{
|
||||||
Task::checkSanity("sys$open");
|
Task::checkSanity("sys$open");
|
||||||
|
#ifdef DEBUG_IO
|
||||||
kprintf("Task::sys$open(): PID=%u, path=%s {%u}\n", m_pid, path, pathLength);
|
kprintf("Task::sys$open(): PID=%u, path=%s {%u}\n", m_pid, path, pathLength);
|
||||||
|
#endif
|
||||||
auto* handle = current->openFile(String(path, pathLength));
|
auto* handle = current->openFile(String(path, pathLength));
|
||||||
if (handle)
|
if (handle)
|
||||||
return handle->fd();
|
return handle->fd();
|
||||||
|
@ -607,14 +643,15 @@ int Task::sys$open(const char* path, size_t pathLength)
|
||||||
|
|
||||||
FileHandle* Task::openFile(String&& path)
|
FileHandle* Task::openFile(String&& path)
|
||||||
{
|
{
|
||||||
kprintf("calling vfs::open with vfs=%p, path='%s'\n", &VirtualFileSystem::the(), path.characters());
|
|
||||||
auto handle = VirtualFileSystem::the().open(move(path));
|
auto handle = VirtualFileSystem::the().open(move(path));
|
||||||
if (!handle) {
|
if (!handle) {
|
||||||
kprintf("vfs::open() failed\n");
|
kprintf("vfs::open() failed\n");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
handle->setFD(m_fileHandles.size());
|
handle->setFD(m_fileHandles.size());
|
||||||
|
#ifdef DEBUG_IO
|
||||||
kprintf("vfs::open() worked! handle=%p, fd=%d\n", handle.ptr(), handle->fd());
|
kprintf("vfs::open() worked! handle=%p, fd=%d\n", handle.ptr(), handle->fd());
|
||||||
|
#endif
|
||||||
m_fileHandles.append(move(handle)); // FIXME: allow non-move Vector::append
|
m_fileHandles.append(move(handle)); // FIXME: allow non-move Vector::append
|
||||||
return m_fileHandles.last().ptr();
|
return m_fileHandles.last().ptr();
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,7 @@ public:
|
||||||
int sys$geterror() { return m_error; }
|
int sys$geterror() { return m_error; }
|
||||||
void sys$sleep(DWORD ticks);
|
void sys$sleep(DWORD ticks);
|
||||||
void sys$exit(int status);
|
void sys$exit(int status);
|
||||||
|
int sys$spawn(const char* path);
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
|
Binary file not shown.
|
@ -78,6 +78,7 @@ asm( \
|
||||||
" pushw %ss\n" \
|
" pushw %ss\n" \
|
||||||
" pushw %ss\n" \
|
" pushw %ss\n" \
|
||||||
" pushw %ss\n" \
|
" pushw %ss\n" \
|
||||||
|
" pushw %ss\n" \
|
||||||
" popw %ds\n" \
|
" popw %ds\n" \
|
||||||
" popw %es\n" \
|
" popw %es\n" \
|
||||||
" popw %fs\n" \
|
" popw %fs\n" \
|
||||||
|
@ -85,6 +86,7 @@ asm( \
|
||||||
" mov %esp, exception_state_dump\n" \
|
" mov %esp, exception_state_dump\n" \
|
||||||
" call exception_" # ec "_handler\n" \
|
" call exception_" # ec "_handler\n" \
|
||||||
" popw %gs\n" \
|
" popw %gs\n" \
|
||||||
|
" popw %gs\n" \
|
||||||
" popw %fs\n" \
|
" popw %fs\n" \
|
||||||
" popw %es\n" \
|
" popw %es\n" \
|
||||||
" popw %ds\n" \
|
" popw %ds\n" \
|
||||||
|
@ -107,6 +109,7 @@ asm( \
|
||||||
" pushw %ss\n" \
|
" pushw %ss\n" \
|
||||||
" pushw %ss\n" \
|
" pushw %ss\n" \
|
||||||
" pushw %ss\n" \
|
" pushw %ss\n" \
|
||||||
|
" pushw %ss\n" \
|
||||||
" popw %ds\n" \
|
" popw %ds\n" \
|
||||||
" popw %es\n" \
|
" popw %es\n" \
|
||||||
" popw %fs\n" \
|
" popw %fs\n" \
|
||||||
|
@ -114,6 +117,7 @@ asm( \
|
||||||
" mov %esp, exception_state_dump\n" \
|
" mov %esp, exception_state_dump\n" \
|
||||||
" call exception_" # ec "_handler\n" \
|
" call exception_" # ec "_handler\n" \
|
||||||
" popw %gs\n" \
|
" popw %gs\n" \
|
||||||
|
" popw %gs\n" \
|
||||||
" popw %fs\n" \
|
" popw %fs\n" \
|
||||||
" popw %es\n" \
|
" popw %es\n" \
|
||||||
" popw %ds\n" \
|
" popw %ds\n" \
|
||||||
|
|
|
@ -119,6 +119,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RegisterDump {
|
struct RegisterDump {
|
||||||
|
WORD ss;
|
||||||
WORD gs;
|
WORD gs;
|
||||||
WORD fs;
|
WORD fs;
|
||||||
WORD es;
|
WORD es;
|
||||||
|
|
|
@ -28,6 +28,7 @@ asm(
|
||||||
" pushw %ss\n"
|
" pushw %ss\n"
|
||||||
" pushw %ss\n"
|
" pushw %ss\n"
|
||||||
" pushw %ss\n"
|
" pushw %ss\n"
|
||||||
|
" pushw %ss\n"
|
||||||
" popw %ds\n"
|
" popw %ds\n"
|
||||||
" popw %es\n"
|
" popw %es\n"
|
||||||
" popw %fs\n"
|
" popw %fs\n"
|
||||||
|
@ -35,6 +36,7 @@ asm(
|
||||||
" mov %esp, state_dump\n"
|
" mov %esp, state_dump\n"
|
||||||
" call clock_handle\n"
|
" call clock_handle\n"
|
||||||
" popw %gs\n"
|
" popw %gs\n"
|
||||||
|
" popw %gs\n"
|
||||||
" popw %fs\n"
|
" popw %fs\n"
|
||||||
" popw %es\n"
|
" popw %es\n"
|
||||||
" popw %ds\n"
|
" popw %ds\n"
|
||||||
|
@ -117,13 +119,18 @@ void clock_handle()
|
||||||
// If this IRQ occurred while in a user task, wouldn't that also push the stack ptr?
|
// If this IRQ occurred while in a user task, wouldn't that also push the stack ptr?
|
||||||
current->tss().esp = regs.esp + 12;
|
current->tss().esp = regs.esp + 12;
|
||||||
|
|
||||||
// FIXME: Is this really safe? What if the interrupted process didn't have SS==DS?
|
current->tss().ss = regs.ss;
|
||||||
current->tss().ss = regs.ds;
|
|
||||||
|
|
||||||
if ((current->tss().cs & 3) != 0) {
|
if ((current->tss().cs & 3) != 0) {
|
||||||
// What do I do now?
|
#if 0
|
||||||
kprintf("clk'ed across to ring0\n");
|
kprintf("clock'ed across to ring0\n");
|
||||||
HANG;
|
kprintf("code: %w:%x\n", current->tss().cs, current->tss().eip);
|
||||||
|
kprintf(" stk: %w:%x\n", current->tss().ss, current->tss().esp);
|
||||||
|
kprintf("astk: %w:%x\n", regs.ss_if_crossRing, regs.esp_if_crossRing);
|
||||||
|
//HANG;
|
||||||
|
#endif
|
||||||
|
current->tss().ss = regs.ss_if_crossRing;
|
||||||
|
current->tss().esp = regs.esp_if_crossRing;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare a new task to run;
|
// Prepare a new task to run;
|
||||||
|
|
|
@ -99,13 +99,12 @@ static void init_stage2()
|
||||||
{
|
{
|
||||||
kprintf("init stage2...\n");
|
kprintf("init stage2...\n");
|
||||||
|
|
||||||
// Anything that registers interrupts goes *after* PIC and IDT for obvious reasons.
|
|
||||||
Syscall::initialize();
|
Syscall::initialize();
|
||||||
|
|
||||||
|
auto keyboard = make<Keyboard>();
|
||||||
|
|
||||||
extern void panel_main();
|
extern void panel_main();
|
||||||
|
|
||||||
new Task(panel_main, "panel", IPC::Handle::PanelTask, Task::Ring0);
|
new Task(panel_main, "panel", IPC::Handle::PanelTask, Task::Ring0);
|
||||||
|
|
||||||
//new Task(led_disco, "led-disco", IPC::Handle::Any, Task::Ring0);
|
//new Task(led_disco, "led-disco", IPC::Handle::Any, Task::Ring0);
|
||||||
|
|
||||||
Disk::initialize();
|
Disk::initialize();
|
||||||
|
@ -125,6 +124,8 @@ static void init_stage2()
|
||||||
auto dev_random = make<RandomDevice>();
|
auto dev_random = make<RandomDevice>();
|
||||||
vfs->registerCharacterDevice(1, 8, *dev_random);
|
vfs->registerCharacterDevice(1, 8, *dev_random);
|
||||||
|
|
||||||
|
vfs->registerCharacterDevice(85, 1, *keyboard);
|
||||||
|
|
||||||
auto dev_hd0 = IDEDiskDevice::create();
|
auto dev_hd0 = IDEDiskDevice::create();
|
||||||
auto e2fs = Ext2FileSystem::create(dev_hd0.copyRef());
|
auto e2fs = Ext2FileSystem::create(dev_hd0.copyRef());
|
||||||
e2fs->initialize();
|
e2fs->initialize();
|
||||||
|
@ -167,7 +168,9 @@ static void init_stage2()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto* idTask = Task::create("/bin/id", (uid_t)209, (gid_t)1985);
|
//auto* idTask = Task::create("/bin/id", (uid_t)209, (gid_t)1985);
|
||||||
|
|
||||||
|
auto* shTask = Task::create("/bin/sh", (uid_t)100, (gid_t)100);
|
||||||
|
|
||||||
//new Task(motd_main, "motd", IPC::Handle::MotdTask, Task::Ring0);
|
//new Task(motd_main, "motd", IPC::Handle::MotdTask, Task::Ring0);
|
||||||
//new Task(syscall_test_main, "syscall_test", IPC::Handle::MotdTask, Task::Ring3);
|
//new Task(syscall_test_main, "syscall_test", IPC::Handle::MotdTask, Task::Ring3);
|
||||||
|
@ -206,8 +209,6 @@ void init()
|
||||||
VirtualFileSystem::initializeGlobals();
|
VirtualFileSystem::initializeGlobals();
|
||||||
StringImpl::initializeGlobals();
|
StringImpl::initializeGlobals();
|
||||||
|
|
||||||
auto keyboard = make<Keyboard>();
|
|
||||||
|
|
||||||
PIT::initialize();
|
PIT::initialize();
|
||||||
|
|
||||||
memset(&system, 0, sizeof(system));
|
memset(&system, 0, sizeof(system));
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
|
|
||||||
#define CRASH() do { asm volatile("ud2"); } while(0)
|
#define CRASH() do { asm volatile("ud2"); } while(0)
|
||||||
#define ASSERT(x) do { if (!(x)) { kprintf("ASSERTION FAILED: " #x "\n%s:%u in %s\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); CRASH(); } } while(0)
|
#define ASSERT(x) do { if (!(x)) { asm volatile("cli"); kprintf("ASSERTION FAILED: " #x "\n%s:%u in %s\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); CRASH(); } } while(0)
|
||||||
#define RELEASE_ASSERT(x) do { if (!(x)) CRASH(); } while(0)
|
#define RELEASE_ASSERT(x) do { if (!(x)) CRASH(); } while(0)
|
||||||
#define ASSERT_NOT_REACHED() ASSERT(false)
|
#define ASSERT_NOT_REACHED() ASSERT(false)
|
||||||
|
|
5
Kernel/sync-sh
Executable file
5
Kernel/sync-sh
Executable file
|
@ -0,0 +1,5 @@
|
||||||
|
mkdir mnt
|
||||||
|
mount -o loop _fs_contents mnt/
|
||||||
|
cp ../Userland/sh mnt/bin/sh
|
||||||
|
umount mnt
|
||||||
|
sync
|
|
@ -1,6 +1,8 @@
|
||||||
OBJS = \
|
OBJS = \
|
||||||
stdio.o \
|
stdio.o \
|
||||||
unistd.o \
|
unistd.o \
|
||||||
|
string.o \
|
||||||
|
process.o \
|
||||||
entry.o
|
entry.o
|
||||||
|
|
||||||
LIBRARY = LibC.a
|
LIBRARY = LibC.a
|
||||||
|
|
12
LibC/process.cpp
Normal file
12
LibC/process.cpp
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include "process.h"
|
||||||
|
#include <Kernel/Syscall.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
int spawn(const char* path)
|
||||||
|
{
|
||||||
|
return Syscall::invoke(Syscall::Spawn, (dword)path);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
8
LibC/process.h
Normal file
8
LibC/process.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
int spawn(const char* path);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -141,7 +141,8 @@ extern "C" {
|
||||||
|
|
||||||
int putchar(int ch)
|
int putchar(int ch)
|
||||||
{
|
{
|
||||||
return ch;
|
Syscall::invoke(Syscall::PutCharacter, ch);
|
||||||
|
return (byte)ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
int printf(const char* fmt, ...)
|
int printf(const char* fmt, ...)
|
||||||
|
|
14
LibC/string.cpp
Normal file
14
LibC/string.cpp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
size_t strlen(const char* str)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
while (*(str++))
|
||||||
|
++len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
10
LibC/string.h
Normal file
10
LibC/string.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
size_t strlen(const char*);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -6,9 +6,16 @@ typedef unsigned int dword;
|
||||||
typedef unsigned short word;
|
typedef unsigned short word;
|
||||||
typedef unsigned char byte;
|
typedef unsigned char byte;
|
||||||
|
|
||||||
|
typedef signed int signed_dword;
|
||||||
|
typedef signed short signed_word;
|
||||||
|
typedef signed char signed_byte;
|
||||||
|
|
||||||
typedef dword uid_t;
|
typedef dword uid_t;
|
||||||
typedef dword gid_t;
|
typedef dword gid_t;
|
||||||
typedef dword pid_t;
|
typedef dword pid_t;
|
||||||
|
|
||||||
|
typedef dword size_t;
|
||||||
|
typedef signed_dword ssize_t;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "unistd.h"
|
#include "unistd.h"
|
||||||
|
#include "string.h"
|
||||||
#include <Kernel/Syscall.h>
|
#include <Kernel/Syscall.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -18,5 +19,21 @@ uid_t getpid()
|
||||||
return Syscall::invoke(Syscall::PosixGetpid);
|
return Syscall::invoke(Syscall::PosixGetpid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int open(const char* path)
|
||||||
|
{
|
||||||
|
size_t length = strlen(path);
|
||||||
|
return Syscall::invoke(Syscall::PosixOpen, (dword)path, (dword)length);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t read(int fd, void* buf, size_t count)
|
||||||
|
{
|
||||||
|
return Syscall::invoke(Syscall::PosixRead, (dword)fd, (dword)buf, (dword)count);
|
||||||
|
}
|
||||||
|
|
||||||
|
int close(int fd)
|
||||||
|
{
|
||||||
|
return Syscall::invoke(Syscall::PosixClose, fd);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,9 @@ extern "C" {
|
||||||
uid_t getuid();
|
uid_t getuid();
|
||||||
gid_t getgid();
|
gid_t getgid();
|
||||||
pid_t getpid();
|
pid_t getpid();
|
||||||
|
int open(const char* path);
|
||||||
|
ssize_t read(int fd, void* buf, size_t count);
|
||||||
|
int close(int fd);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
Userland/.gitignore
vendored
1
Userland/.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
id
|
id
|
||||||
|
sh
|
||||||
*.o
|
*.o
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
OBJS = \
|
OBJS = \
|
||||||
id.o
|
id.o \
|
||||||
|
sh.o
|
||||||
|
|
||||||
APPS = \
|
APPS = \
|
||||||
id
|
id \
|
||||||
|
sh
|
||||||
|
|
||||||
ARCH_FLAGS =
|
ARCH_FLAGS =
|
||||||
STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib
|
STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib
|
||||||
|
@ -25,6 +27,9 @@ all: $(OBJS) $(APPS)
|
||||||
id: id.o
|
id: id.o
|
||||||
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
||||||
|
|
||||||
|
sh: sh.o
|
||||||
|
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
||||||
|
|
||||||
.cpp.o:
|
.cpp.o:
|
||||||
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
|
56
Userland/sh.cpp
Normal file
56
Userland/sh.cpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#include <LibC/stdio.h>
|
||||||
|
#include <LibC/unistd.h>
|
||||||
|
#include <LibC/process.h>
|
||||||
|
|
||||||
|
static void prompt()
|
||||||
|
{
|
||||||
|
if (getuid() == 0)
|
||||||
|
printf("# ");
|
||||||
|
else
|
||||||
|
printf("$ ");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int runcmd(char* cmd)
|
||||||
|
{
|
||||||
|
//printf("command: '%s'\n", cmd);
|
||||||
|
int ret = spawn(cmd);
|
||||||
|
if (ret == -1) {
|
||||||
|
printf("spawn failed: %s\n", cmd);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int c, char** v)
|
||||||
|
{
|
||||||
|
char linebuf[128];
|
||||||
|
int linedx = 0;
|
||||||
|
linebuf[0] = '\0';
|
||||||
|
|
||||||
|
int fd = open("/dev/keyboard");
|
||||||
|
if (fd == -1) {
|
||||||
|
printf("failed to open /dev/keyboard :(\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
prompt();
|
||||||
|
for (;;) {
|
||||||
|
char keybuf[16];
|
||||||
|
ssize_t nread = read(fd, keybuf, sizeof(keybuf));
|
||||||
|
if (nread < 0) {
|
||||||
|
printf("failed to read :(\n");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
for (ssize_t i = 0; i < nread; ++i) {
|
||||||
|
putchar(keybuf[i]);
|
||||||
|
if (keybuf[i] != '\n') {
|
||||||
|
linebuf[linedx++] = keybuf[i];
|
||||||
|
linebuf[linedx] = '\0';
|
||||||
|
} else {
|
||||||
|
runcmd(linebuf);
|
||||||
|
linebuf[0] = '\0';
|
||||||
|
linedx = 0;
|
||||||
|
prompt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue