diff --git a/desktop/posix.cpp b/desktop/posix.cpp index 66c32fb..4480cf9 100644 --- a/desktop/posix.cpp +++ b/desktop/posix.cpp @@ -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; diff --git a/kernel/posix.cpp b/kernel/posix.cpp index 33748c1..110a15a 100644 --- a/kernel/posix.cpp +++ b/kernel/posix.cpp @@ -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); diff --git a/kernel/syscall.cpp b/kernel/syscall.cpp index 9567080..7ecdbc9 100644 --- a/kernel/syscall.cpp +++ b/kernel/syscall.cpp @@ -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); }