update POSIX subsystem

This commit is contained in:
nakst 2021-09-11 15:57:08 +01:00
parent 1ad024a542
commit 243166f370
3 changed files with 90 additions and 40 deletions

View File

@ -685,9 +685,11 @@ long EsPOSIXSystemCall(long n, long a1, long a2, long a3, long a4, long a5, long
}
void EsPOSIXInitialise(int *argc, char ***argv) {
EsProcessStartupInformation *startupInformation = ProcessGetStartupInformation();
// Get the arguments and environment.
EsHandle environmentHandle = EsSyscall(ES_SYSCALL_PROCESS_GET_CREATION_ARGUMENT, ES_CURRENT_PROCESS, CREATION_ARGUMENT_ENVIRONMENT, 0, 0);
EsHandle environmentHandle = startupInformation->data.environment;
char *environmentBuffer = (char *) "./application\0\0LANG=en_US.UTF-8\0PWD=/\0HOME=/\0PATH=/Applications/POSIX/bin\0TMPDIR=/Applications/POSIX/tmp\0\0";
if (environmentHandle) {
@ -740,8 +742,6 @@ void EsPOSIXInitialise(int *argc, char ***argv) {
// Add the auxillary vectors.
EsProcessStartupInformation *startupInformation = ProcessGetStartupInformation();
#ifdef ARCH_X86_64
Elf64_Phdr *tlsHeader = (Elf64_Phdr *) EsHeapAllocate(sizeof(Elf64_Phdr), true);
tlsHeader->p_type = PT_TLS;

View File

@ -45,10 +45,18 @@ struct POSIXThread {
MMRegion *_region ## index = MMFindAndPinRegion(currentVMM, (address), (length)); \
EsDefer(if (_region ## index) MMUnpinRegion(currentVMM, _region ## index));
#define SYSCALL_HANDLE_POSIX(handle, __object, index) \
KObject _object ## index(handleTable, ConvertStandardInputTo3(handle), KERNEL_OBJECT_POSIX_FD); \
*((void **) &__object) = _object ## index .object; \
if (! _object ## index .valid) return -EBADF; else _object ## index .checked = true; \
#define SYSCALL_HANDLE_POSIX_2(handle, out) \
Handle _ ## out; \
uint8_t status_ ## out = currentProcess->handleTable.ResolveHandle(&_ ## out, ConvertStandardInputTo3(handle), KERNEL_OBJECT_POSIX_FD); \
if (status_ ## out == RESOLVE_HANDLE_FAILED) return -EBADF; \
EsDefer(if (status_ ## out == RESOLVE_HANDLE_NORMAL) CloseHandleToObject(_ ## out.object, _ ## out.type, _ ## out.flags)); \
const Handle out = _ ## out
#define SYSCALL_HANDLE_POSIX(handle, out) \
Handle _ ## out; \
uint8_t status_ ## out = currentProcess->handleTable.ResolveHandle(&_ ## out, ConvertStandardInputTo3(handle), KERNEL_OBJECT_POSIX_FD); \
if (status_ ## out == RESOLVE_HANDLE_FAILED) return -EBADF; \
EsDefer(if (status_ ## out == RESOLVE_HANDLE_NORMAL) CloseHandleToObject(_ ## out.object, _ ## out.type, _ ## out.flags)); \
POSIXFile *const out = (POSIXFile *) _ ## out.object
#endif
@ -277,8 +285,7 @@ namespace POSIX {
case ES_POSIX_SYSCALL_GET_POSIX_FD_PATH: {
if (syscall.arguments[2] > SYSCALL_BUFFER_LIMIT) return -ENOMEM;
POSIXFile *file;
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file, 1);
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file);
SYSCALL_BUFFER_POSIX(syscall.arguments[1], syscall.arguments[2], 2, true);
KMutexAcquire(&file->mutex);
EsDefer(KMutexRelease(&file->mutex));
@ -298,8 +305,7 @@ namespace POSIX {
} break;
case SYS_fstat: {
POSIXFile *file;
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file, 1);
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file);
SYSCALL_BUFFER_POSIX(syscall.arguments[1], sizeof(struct stat), 1, true);
struct stat temp;
KMutexAcquire(&file->mutex);
@ -310,33 +316,30 @@ namespace POSIX {
} break;
case SYS_fcntl: {
POSIXFile *file;
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file, 1);
SYSCALL_HANDLE_POSIX_2(syscall.arguments[0], fd);
POSIXFile *file = (POSIXFile *) fd.object;
if (syscall.arguments[1] == F_GETFD) {
return _object1.flags;
return fd.flags;
} else if (syscall.arguments[1] == F_SETFD) {
KObject object;
uint32_t newFlags = syscall.arguments[2];
handleTable->ModifyFlags(syscall.arguments[0], newFlags);
handleTable->ModifyFlags(syscall.arguments[0], syscall.arguments[2]);
} else if (syscall.arguments[1] == F_GETFL) {
return file->posixFlags;
} else if (syscall.arguments[1] == F_DUPFD) {
// Duplicate with FD_CLOEXEC clear.
OpenHandleToObject(file, KERNEL_OBJECT_POSIX_FD, 0);
return handleTable->OpenHandle(_object1.object, 0, _object1.type) ?: -ENFILE;
return handleTable->OpenHandle(fd.object, 0, fd.type) ?: -ENFILE;
} else if (syscall.arguments[1] == F_DUPFD_CLOEXEC) {
// Duplicate with FD_CLOEXEC set.
OpenHandleToObject(file, KERNEL_OBJECT_POSIX_FD, FD_CLOEXEC);
return handleTable->OpenHandle(_object1.object, FD_CLOEXEC, _object1.type) ?: -ENFILE;
return handleTable->OpenHandle(fd.object, FD_CLOEXEC, fd.type) ?: -ENFILE;
} else {
KernelPanic("POSIX::DoSyscall - Unimplemented fcntl %d.\n", syscall.arguments[1]);
}
} break;
case SYS_lseek: {
POSIXFile *file;
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file, 1);
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file);
KMutexAcquire(&file->mutex);
EsDefer(KMutexRelease(&file->mutex));
@ -355,8 +358,7 @@ namespace POSIX {
} break;
case SYS_ioctl: {
POSIXFile *file;
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file, 1);
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file);
KMutexAcquire(&file->mutex);
EsDefer(KMutexRelease(&file->mutex));
@ -377,16 +379,14 @@ namespace POSIX {
} break;
case SYS_read: {
POSIXFile *file;
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file, 1);
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file);
SYSCALL_BUFFER_POSIX(syscall.arguments[1], syscall.arguments[2], 3, false);
return Read(file, (void *) syscall.arguments[1], syscall.arguments[2], _region3->flags & MM_REGION_FILE);
} break;
case SYS_readv: {
POSIXFile *file;
if (syscall.arguments[2] > 1024) return -EINVAL;
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file, 1);
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file);
SYSCALL_BUFFER_POSIX(syscall.arguments[1], syscall.arguments[2] * sizeof(struct iovec *), 2, false);
struct iovec *vectors = (struct iovec *) EsHeapAllocate(syscall.arguments[2] * sizeof(struct iovec), false, K_FIXED);
@ -408,8 +408,7 @@ namespace POSIX {
} break;
case SYS_write: {
POSIXFile *file;
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file, 1);
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file);
SYSCALL_BUFFER_POSIX(syscall.arguments[1], syscall.arguments[2], 3, true);
if (file->type == POSIX_FILE_NORMAL && !(file->openFlags & (ES_FILE_WRITE_SHARED | ES_FILE_WRITE))) {
@ -420,9 +419,8 @@ namespace POSIX {
} break;
case SYS_writev: {
POSIXFile *file;
if (syscall.arguments[2] > 1024) return -EINVAL;
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file, 1);
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file);
SYSCALL_BUFFER_POSIX(syscall.arguments[1], syscall.arguments[2] * sizeof(struct iovec *), 2, false);
struct iovec *vectors = (struct iovec *) EsHeapAllocate(syscall.arguments[2] * sizeof(struct iovec), false, K_FIXED);
@ -504,7 +502,7 @@ namespace POSIX {
EsMemoryCopy(path, (void *) syscall.arguments[0], syscall.arguments[1]);
Process *process = currentThread->posixData->forkProcess;
process->creationArguments[CREATION_ARGUMENT_ENVIRONMENT] = MakeConstantBuffer((void *) syscall.arguments[2], syscall.arguments[3], process);
process->data.environment = MakeConstantBuffer((void *) syscall.arguments[2], syscall.arguments[3], process);
process->posixForking = true;
process->permissions = currentProcess->permissions;
@ -512,7 +510,7 @@ namespace POSIX {
OpenHandleToObject((void *) syscall.arguments[4], KERNEL_OBJECT_NODE, _ES_NODE_DIRECTORY_WRITE);
mountPoint.base = process->handleTable.OpenHandle((void *) syscall.arguments[4], _ES_NODE_DIRECTORY_WRITE, KERNEL_OBJECT_NODE);
mountPoint.prefixBytes = EsStringFormat(mountPoint.prefix, sizeof(mountPoint.prefix), "|POSIX:");
process->creationArguments[CREATION_ARGUMENT_INITIAL_MOUNT_POINTS] = MakeConstantBuffer(&mountPoint, sizeof(EsMountPoint), process);
process->data.initialMountPoints = MakeConstantBuffer(&mountPoint, sizeof(EsMountPoint), process);
// Start the process.
@ -612,8 +610,8 @@ namespace POSIX {
} break;
case SYS_dup2: {
POSIXFile *file;
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file, 1);
SYSCALL_HANDLE_POSIX_2(syscall.arguments[0], fd);
POSIXFile *file = (POSIXFile *) fd.object;
// Try to close the newfd.
@ -621,9 +619,8 @@ namespace POSIX {
// Clone the oldfd as newfd.
OpenHandleToObject(file, KERNEL_OBJECT_POSIX_FD, _object1.flags);
return handleTable->OpenHandle(_object1.object, _object1.flags, _object1.type,
ConvertStandardInputTo3(syscall.arguments[1])) ? 0 : -EBUSY;
OpenHandleToObject(file, KERNEL_OBJECT_POSIX_FD, fd.flags);
return handleTable->OpenHandle(fd.object, fd.flags, fd.type, ConvertStandardInputTo3(syscall.arguments[1])) ? 0 : -EBUSY;
} break;
case SYS_pipe2: {
@ -672,8 +669,7 @@ namespace POSIX {
if (syscall.arguments[2] > SYSCALL_BUFFER_LIMIT) return -ENOMEM;
POSIXFile *file;
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file, 1);
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file);
SYSCALL_BUFFER_POSIX(syscall.arguments[1], syscall.arguments[2], 3, true);
KMutexAcquire(&file->mutex);

View File

@ -257,6 +257,60 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_PROCESS_CREATE) {
}
// TODO.
#if 0
Process *process = scheduler.SpawnProcess();
if (!process) {
SYSCALL_RETURN(ES_ERROR_INSUFFICIENT_RESOURCES, false);
}
process->creationFlags = arguments.flags;
process->creationArguments[CREATION_ARGUMENT_MAIN] = arguments.creationArgument.u;
process->permissions = arguments.permissions;
// TODO Free the process object if something fails here.
if (arguments.environmentBlockBytes) {
if (arguments.environmentBlockBytes > SYSCALL_BUFFER_LIMIT) SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_BUFFER, true);
SYSCALL_BUFFER((uintptr_t) arguments.environmentBlock, arguments.environmentBlockBytes, 1, false);
process->creationArguments[CREATION_ARGUMENT_ENVIRONMENT] = MakeConstantBuffer(arguments.environmentBlock, arguments.environmentBlockBytes, process);
}
if (arguments.initialMountPointCount) {
if (arguments.initialMountPointCount > ES_MOUNT_POINT_MAX_COUNT) SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_BUFFER, true);
EsMountPoint *mountPoints = (EsMountPoint *) EsHeapAllocate(arguments.initialMountPointCount * sizeof(EsMountPoint), false, K_FIXED);
EsDefer(EsHeapFree(mountPoints, arguments.initialMountPointCount * sizeof(EsMountPoint), K_FIXED));
SYSCALL_READ(mountPoints, (uintptr_t) arguments.initialMountPoints, arguments.initialMountPointCount * sizeof(EsMountPoint));
for (uintptr_t i = 0; i < arguments.initialMountPointCount; i++) {
// Open handles to the mount points for the new process.
// TODO Handling errors when opening handles.
KObject object(currentProcess, mountPoints[i].base, KERNEL_OBJECT_NODE);
CHECK_OBJECT(object);
if (!mountPoints[i].write) object.flags &= ~_ES_NODE_DIRECTORY_WRITE;
OpenHandleToObject(object.object, object.type, object.flags);
mountPoints[i].base = process->handleTable.OpenHandle(object.object, object.flags, object.type);
}
process->creationArguments[CREATION_ARGUMENT_INITIAL_MOUNT_POINTS]
= MakeConstantBuffer(mountPoints, arguments.initialMountPointCount * sizeof(EsMountPoint), process);
}
if (!process->StartWithNode((KNode *) executableObject.object)) {
CloseHandleToObject(process, KERNEL_OBJECT_PROCESS);
SYSCALL_RETURN(ES_ERROR_UNKNOWN, false);
}
processInformation.pid = process->id;
processInformation.mainThread.tid = process->executableMainThread->id;
processInformation.mainThread.handle = currentProcess->handleTable.OpenHandle(process->executableMainThread, 0, KERNEL_OBJECT_THREAD);
processInformation.handle = currentProcess->handleTable.OpenHandle(process, 0, KERNEL_OBJECT_PROCESS);
SYSCALL_WRITE(argument2, &processInformation, sizeof(EsProcessInformation));
SYSCALL_RETURN(ES_SUCCESS, false);
#endif
SYSCALL_RETURN(ES_FATAL_ERROR_UNKNOWN_SYSCALL, true);
}