rewrite init to restart failed processes, add file renaming, directory creation, directory renaming, directory removal, add process killing, unify shells, readme changes.
This commit is contained in:
1 parent
f80e66ecde
commit
ddb074f0e0
16 files changed
+476
-641
No files matched your search
@@ -289,6 +289,48 @@ __declspec(dllexport) KSTATUS IoDeleteFile(const char* path) {
|
||||
return fs->Delete(fs, relPath);
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS IoRenameFile(const char* oldPath, const char* newPath) {
|
||||
if (!oldPath || !newPath) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
char oldRel[CWD_MAX];
|
||||
char newRel[CWD_MAX];
|
||||
uint8_t oldDrive = ResolvePath(oldPath, oldRel, sizeof(oldRel));
|
||||
uint8_t newDrive = ResolvePath(newPath, newRel, sizeof(newRel));
|
||||
if (oldDrive != newDrive) return STATUS_NOT_SUPPORTED;
|
||||
|
||||
IO_FILESYSTEM* fs = gVolumes[oldDrive].Fs;
|
||||
if (!fs) return STATUS_NOT_FOUND;
|
||||
if (!fs->Rename) return STATUS_NOT_SUPPORTED;
|
||||
|
||||
return fs->Rename(fs, oldRel, newRel);
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS IoCreateDir(const char* path) {
|
||||
if (!path) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
char relPath[CWD_MAX];
|
||||
uint8_t drive = ResolvePath(path, relPath, sizeof(relPath));
|
||||
|
||||
IO_FILESYSTEM* fs = gVolumes[drive].Fs;
|
||||
if (!fs) return STATUS_NOT_FOUND;
|
||||
if (!fs->CreateDir) return STATUS_NOT_SUPPORTED;
|
||||
|
||||
return fs->CreateDir(fs, relPath);
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS IoRemoveDir(const char* path) {
|
||||
if (!path) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
char relPath[CWD_MAX];
|
||||
uint8_t drive = ResolvePath(path, relPath, sizeof(relPath));
|
||||
|
||||
IO_FILESYSTEM* fs = gVolumes[drive].Fs;
|
||||
if (!fs) return STATUS_NOT_FOUND;
|
||||
if (!fs->RemoveDir) return STATUS_NOT_SUPPORTED;
|
||||
|
||||
return fs->RemoveDir(fs, relPath);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// IoTruncateFile - resize the file; updates the cached Size on success
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -45,6 +45,14 @@ typedef struct IO_FILESYSTEM {
|
||||
// Delete the file at 'path'.
|
||||
KSTATUS (*Delete)(struct IO_FILESYSTEM* fs, const char* path);
|
||||
|
||||
// Rename or move a file/directory within the same filesystem.
|
||||
KSTATUS (*Rename)(struct IO_FILESYSTEM* fs,
|
||||
const char* oldPath, const char* newPath);
|
||||
|
||||
// Create or remove directories.
|
||||
KSTATUS (*CreateDir)(struct IO_FILESYSTEM* fs, const char* path);
|
||||
KSTATUS (*RemoveDir)(struct IO_FILESYSTEM* fs, const char* path);
|
||||
|
||||
// Truncate or extend the file to exactly 'newSize' bytes.
|
||||
KSTATUS (*Truncate)(struct IO_FILESYSTEM* fs, void* fileCtx,
|
||||
uint64_t newSize);
|
||||
@@ -119,6 +127,9 @@ __declspec(dllexport) KSTATUS IoWriteFile (FILE_OBJECT* file, const void* buf,
|
||||
size_t size, size_t* bytesWritten);
|
||||
__declspec(dllexport) KSTATUS IoCreateFile (const char* path, FILE_OBJECT** out);
|
||||
__declspec(dllexport) KSTATUS IoDeleteFile (const char* path);
|
||||
__declspec(dllexport) KSTATUS IoRenameFile (const char* oldPath, const char* newPath);
|
||||
__declspec(dllexport) KSTATUS IoCreateDir (const char* path);
|
||||
__declspec(dllexport) KSTATUS IoRemoveDir (const char* path);
|
||||
__declspec(dllexport) KSTATUS IoTruncateFile(FILE_OBJECT* file, uint64_t newSize);
|
||||
__declspec(dllexport) KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset);
|
||||
__declspec(dllexport) uint64_t IoGetFileSize(FILE_OBJECT* file);
|
||||
|
||||
@@ -25,6 +25,7 @@ static void ProcessInit(void) {
|
||||
}
|
||||
|
||||
LIST_ENTRY* KeGetProcessList(void) {
|
||||
ProcessInit();
|
||||
return &gProcessList;
|
||||
}
|
||||
|
||||
@@ -36,6 +37,21 @@ PROCESS* KeGetCurrentProcess(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t KeCopyProcessIds(uint32_t* pidsOut, size_t maxCount) {
|
||||
ProcessInit();
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gProcessListLock);
|
||||
size_t count = 0;
|
||||
LIST_ENTRY* head = &gProcessList;
|
||||
for (LIST_ENTRY* node = head->Fwd; node != head; node = node->Fwd) {
|
||||
PROCESS* p = CONTAINING_RECORD(node, PROCESS, GlobalLink);
|
||||
if (pidsOut && count < maxCount) pidsOut[count] = p->ProcessId;
|
||||
count++;
|
||||
}
|
||||
KeReleaseSpinlock(&gProcessListLock, flags);
|
||||
return count;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Destructor (called by ObDereferenceObject when RefCount hits zero)
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -206,6 +222,7 @@ OBJECT* KeLookupHandle(PROCESS* process, uint32_t handle) {
|
||||
}
|
||||
|
||||
PROCESS* KeGetProcessById(uint32_t pid) {
|
||||
ProcessInit();
|
||||
uintptr_t flags = KeAcquireSpinlock(&gProcessListLock);
|
||||
LIST_ENTRY* head = &gProcessList;
|
||||
LIST_ENTRY* node = head->Fwd;
|
||||
|
||||
@@ -77,5 +77,7 @@ OBJECT* KeLookupHandle(PROCESS* process, uint32_t handle);
|
||||
/* Return the global process list head (kernel-internal). */
|
||||
LIST_ENTRY* KeGetProcessList(void);
|
||||
PROCESS* KeGetCurrentProcess(void);
|
||||
/* Copy a snapshot of process IDs into caller-provided storage. */
|
||||
size_t KeCopyProcessIds(uint32_t* pidsOut, size_t maxCount);
|
||||
/* Find a live process by its ProcessId. Bumps refcount; caller must ObDereferenceObject. */
|
||||
PROCESS* KeGetProcessById(uint32_t pid);
|
||||
@@ -1177,6 +1177,72 @@ static uint64_t SyscallNamedQueueOwnerPid(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
static uint64_t SyscallKillProcess(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a2; (void)a3; (void)a4; (void)a5;
|
||||
PROCESS* proc = KeGetProcessById((uint32_t)a0);
|
||||
if (!proc) return STATUS_NOT_FOUND;
|
||||
THREAD* self = KeGetCurrentThread();
|
||||
int exitCode = (int)a1;
|
||||
if (self && self->Owner == proc) {
|
||||
KeExitProcess(proc, exitCode);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
KeExitThread(self, exitCode);
|
||||
while (true) ;
|
||||
}
|
||||
KeExitProcess(proc, exitCode);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_GET_PROCESS_LIST (65) a0=*pidsOut a1=maxCount a2=*countOut
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallGetProcessList(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a3; (void)a4; (void)a5;
|
||||
uint32_t* pidsOut = (uint32_t*)(uintptr_t)a0;
|
||||
size_t maxCount = (size_t)a1;
|
||||
size_t* countOut = (size_t*)(uintptr_t)a2;
|
||||
size_t count = KeCopyProcessIds(pidsOut, maxCount);
|
||||
if (countOut) *countOut = count;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_RENAME_FILE (66) a0=*oldPath a1=*newPath
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallRenameFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a2; (void)a3; (void)a4; (void)a5;
|
||||
const char* oldPath = (const char*)(uintptr_t)a0;
|
||||
const char* newPath = (const char*)(uintptr_t)a1;
|
||||
if (!oldPath || !newPath) return STATUS_INVALID_PARAMETER;
|
||||
return IoRenameFile(oldPath, newPath);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_CREATE_DIR (67) a0=*path
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallCreateDir(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
const char* path = (const char*)(uintptr_t)a0;
|
||||
if (!path) return STATUS_INVALID_PARAMETER;
|
||||
return IoCreateDir(path);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_REMOVE_DIR (68) a0=*path
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallRemoveDir(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
const char* path = (const char*)(uintptr_t)a0;
|
||||
if (!path) return STATUS_INVALID_PARAMETER;
|
||||
return IoRemoveDir(path);
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Dispatch table - index must match SYS_* in syscall_nr.h exactly.
|
||||
// ===========================================================================
|
||||
@@ -1248,6 +1314,11 @@ static const SYSCALL_HANDLER gSyscallTable[SYS_MAX] = {
|
||||
/* 61 SYS_OPEN_NAMED_QUEUE */ SyscallOpenNamedQueue,
|
||||
/* 62 SYS_QUEUE_DUPLICATE */ SyscallQueueDuplicate,
|
||||
/* 63 SYS_NAMED_QUEUE_OWNER_PID */ SyscallNamedQueueOwnerPid,
|
||||
/* 64 SYS_KILL_PROCESS */ SyscallKillProcess,
|
||||
/* 65 SYS_GET_PROCESS_LIST */ SyscallGetProcessList,
|
||||
/* 66 SYS_RENAME_FILE */ SyscallRenameFile,
|
||||
/* 67 SYS_CREATE_DIR */ SyscallCreateDir,
|
||||
/* 68 SYS_REMOVE_DIR */ SyscallRemoveDir,
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
+18
-24
@@ -303,21 +303,6 @@ static PROCESS* LaunchUserProcess(const char* filePath, const char* args) {
|
||||
// Caller owns the reference returned by KeCreateProcess.
|
||||
return proc;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
// Kernel thread: wait for a process to exit, then log a message and shut down.
|
||||
// Takes ownership of the PROCESS* reference passed as arg; releases it on exit.
|
||||
// ---------------------------------------------------------------------------
|
||||
static void ProcessWatcherThread(void* arg) {
|
||||
PROCESS* proc = (PROCESS*)arg;
|
||||
KeWaitForEvent(proc->ExitEvent);
|
||||
DbgPrint("ProcessWatcherThread: Process \"%s\" (PID %u) exited with code %d.\n",
|
||||
proc->Name, proc->ProcessId, proc->ExitCode);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
|
||||
DbgPrint("ProcessWatcherThread: Shutting down.\n");
|
||||
gKmainHal->Power.Shutdown(); // does not return
|
||||
}
|
||||
|
||||
static void PrintProcessList() {
|
||||
LIST_ENTRY* listHead = KeGetProcessList();
|
||||
LIST_ENTRY* current;
|
||||
@@ -354,20 +339,29 @@ void SystemInitThread(void* arg) {
|
||||
DbgPrint(" -> Kernel Pool: %.2f MB\n", (float)MmGetKernelPoolUsage() / (1024.0f * 1024.0f));
|
||||
DbgPrint(" -> User Heap: %.2f MB\n", (float)MmGetUserHeapUsage() / (1024.0f * 1024.0f));
|
||||
|
||||
// Launch User-Mode Shell (this will trigger AHCI & FAT32 which CAN safely block now)
|
||||
PROCESS* shellProc = LaunchUserProcess("system/init.exe", args->bootInfo->CommandLine);
|
||||
|
||||
if (shellProc) {
|
||||
KSTATUS ws = KeCreateKernelThread((uintptr_t)ProcessWatcherThread,
|
||||
(uintptr_t)shellProc,
|
||||
PriorityNormal, (THREAD**)0);
|
||||
if (!KSUCCESS(ws)) {
|
||||
DbgPrint("SystemInitThread: Failed to create watcher thread (%d) -- leaking proc ref.\n", ws);
|
||||
// Launch User-Mode init.exe and restart it until it exits cleanly.
|
||||
while (true) {
|
||||
PROCESS* shellProc = LaunchUserProcess("system/init.exe", args->bootInfo->CommandLine);
|
||||
if (!shellProc) {
|
||||
DbgPrint("SystemInitThread: Failed to start system/init.exe; retrying.\n");
|
||||
KeYield();
|
||||
continue;
|
||||
}
|
||||
|
||||
KeWaitForEvent(shellProc->ExitEvent);
|
||||
int exitCode = shellProc->ExitCode;
|
||||
DbgPrint("SystemInitThread: init.exe exited with code %d.\n", exitCode);
|
||||
ObDereferenceObject(&shellProc->Header);
|
||||
|
||||
if (exitCode == 0) break;
|
||||
DbgPrint("SystemInitThread: Restarting init.exe.\n");
|
||||
}
|
||||
|
||||
DbgPrint("SystemInitThread: init.exe completed successfully; shutting down.\n");
|
||||
gKmainHal->Power.Shutdown();
|
||||
MmFreePool(args);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Main Kernel Entry
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -162,4 +162,17 @@
|
||||
#define SYS_QUEUE_DUPLICATE 62 // (uint32_t handle, uint32_t targetPid, uint32_t* handleOut) -> KSTATUS
|
||||
#define SYS_NAMED_QUEUE_OWNER_PID 63 // (const char* name, uint32_t* pidOut) -> KSTATUS
|
||||
|
||||
#define SYS_MAX 64
|
||||
// ---------------------------------------------------------------------------
|
||||
// Process utilities
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_KILL_PROCESS 64 // (uint32_t pid, int exitCode) -> KSTATUS
|
||||
#define SYS_GET_PROCESS_LIST 65 // (uint32_t* pidsOut, size_t maxCount, size_t* countOut) -> KSTATUS
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Filesystem mutations
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_RENAME_FILE 66 // (const char* oldPath, const char* newPath) -> KSTATUS
|
||||
#define SYS_CREATE_DIR 67 // (const char* path) -> KSTATUS
|
||||
#define SYS_REMOVE_DIR 68 // (const char* path) -> KSTATUS
|
||||
|
||||
#define SYS_MAX 69
|
||||
Reference in new issue
Block a user