Complete os-misc.h with kernel module functions (modfnext, modfind, kldload, kldunload, kldunloadf, kldfind, kldnext, kldstat, kldfirstmod, kldsym), POSIX functions (posix_fallocate, posix_openpt), getrandom, and kenv.
Signed-off-by: Stacey Son <[email protected]> Signed-off-by: Karim Taha <[email protected]> Signed-off-by: Sean Bruno <[email protected]> Signed-off-by: Alexander Kabaev <[email protected]> Signed-off-by: Warner Losh <[email protected]> Assisted-by: Claude Opus 4.6 (1M context) --- bsd-user/freebsd/os-misc.h | 268 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) diff --git a/bsd-user/freebsd/os-misc.h b/bsd-user/freebsd/os-misc.h index 74ed1d2f47..7ee903a5ba 100644 --- a/bsd-user/freebsd/os-misc.h +++ b/bsd-user/freebsd/os-misc.h @@ -270,5 +270,273 @@ static inline abi_long do_freebsd_cpuset_setaffinity(cpulevel_t level, * care. Will reevaluate if examples are found that do matter. */ +/* modfnext(2) */ +static inline abi_long do_freebsd_modfnext(abi_long modid) +{ + return -TARGET_ENOENT; +} + +/* modfind(2) */ +static inline abi_long do_freebsd_modfind(abi_ulong target_name) +{ + return -TARGET_ENOENT; +} + +/* kldload(2) */ +static inline abi_long do_freebsd_kldload(abi_ulong target_name) +{ + return -TARGET_EPERM; +} + +/* kldunload(2) */ +static inline abi_long do_freebsd_kldunload(abi_long fileid) +{ + return -TARGET_EPERM; +} + +/* kldunloadf(2) */ +static inline abi_long do_freebsd_kldunloadf(abi_long fileid, abi_long flags) +{ + return -TARGET_EPERM; +} + +/* kldfind(2) */ +static inline abi_long do_freebsd_kldfind(abi_ulong target_name) +{ + return -TARGET_ENOENT; +} + +/* kldnext(2) */ +static inline abi_long do_freebsd_kldnext(abi_long fileid) +{ + return -TARGET_ENOENT; +} + + +/* kldstat(2) */ +static inline abi_long do_freebsd_kldstat(abi_long fileid, + abi_ulong target_stat) +{ + return -TARGET_ENOENT; +} + +/* kldfirstmod(2) */ +static inline abi_long do_freebsd_kldfirstmod(abi_long fileid) +{ + return -TARGET_ENOENT; +} + +/* kldsym(2) */ +static inline abi_long do_freebsd_kldsym(abi_long fileid, abi_long cmd, + abi_ulong target_data) +{ + return -TARGET_ENOENT; +} + +/* + * New posix calls + */ + +#if TARGET_ABI_BITS == 32 +static inline uint64_t target_offset64(uint32_t word0, uint32_t word1) +{ +#ifdef TARGET_BIG_ENDIAN + return ((uint64_t)word0 << 32) | word1; +#else + return ((uint64_t)word1 << 32) | word0; +#endif +} +#else /* TARGET_ABI_BITS == 32 */ +static inline uint64_t target_offset64(uint64_t word0, uint64_t word1) +{ + return word0; +} +#endif /* TARGET_ABI_BITS != 32 */ + +/* posix_fallocate(2) */ +static inline abi_long do_freebsd_posix_fallocate(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) +{ + +#if TARGET_ABI_BITS == 32 + return get_errno(posix_fallocate(arg1, target_offset64(arg3, arg4), + target_offset64(arg5, arg6))); +#else + return get_errno(posix_fallocate(arg1, arg2, arg3)); +#endif +} + +/* posix_openpt(2) */ +static inline abi_long do_freebsd_posix_openpt(abi_long flags) +{ + + return get_errno(posix_openpt(flags)); +} + +/* + * shm_open2 isn't exported, but the __sys_ alias is. We can use either for the + * static version, but to dynamically link we have to use the sys version. + */ +int __sys_shm_open2(const char *path, int flags, mode_t mode, int shmflags, + const char *); + +/* shm_open2(2) */ +static inline abi_long do_freebsd_shm_open2(abi_ulong pathptr, abi_ulong flags, + abi_long mode, abi_ulong shmflags, abi_ulong nameptr) +{ + int ret; + void *uname, *upath; + + if (pathptr == (uintptr_t)SHM_ANON) { + upath = SHM_ANON; + } else { + upath = lock_user_string(pathptr); + if (upath == NULL) { + return -TARGET_EFAULT; + } + } + + uname = NULL; + if (nameptr != 0) { + uname = lock_user_string(nameptr); + if (uname == NULL) { + unlock_user(upath, pathptr, 0); + return -TARGET_EFAULT; + } + } + ret = get_errno(__sys_shm_open2(upath, + target_to_host_bitmask(flags, fcntl_flags_tbl), mode, + target_to_host_bitmask(shmflags, shmflag_flags_tbl), uname)); + + if (upath != SHM_ANON) { + unlock_user(upath, pathptr, 0); + } + if (uname != NULL) { + unlock_user(uname, nameptr, 0); + } + return ret; +} + +/* shm_rename(2) */ +static inline abi_long do_freebsd_shm_rename(abi_ulong fromptr, abi_ulong toptr, + abi_ulong flags) +{ + int ret; + void *ufrom, *uto; + + ufrom = lock_user_string(fromptr); + if (ufrom == NULL) { + return -TARGET_EFAULT; + } + uto = lock_user_string(toptr); + if (uto == NULL) { + unlock_user(ufrom, fromptr, 0); + return -TARGET_EFAULT; + } + ret = get_errno(shm_rename(ufrom, uto, flags)); + unlock_user(ufrom, fromptr, 0); + unlock_user(uto, toptr, 0); + + return ret; +} + +#if defined(CONFIG_GETRANDOM) +static inline abi_long do_freebsd_getrandom(abi_ulong buf, abi_ulong buflen, + abi_ulong flags) +{ + abi_long ret; + void *p; + + p = lock_user(VERIFY_WRITE, buf, buflen, 0); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(getrandom(p, buflen, flags)); + unlock_user(p, buf, ret); + + return ret; +} +#endif + +static inline abi_long do_freebsd_kenv(abi_long action, abi_ulong name, + abi_ulong value, abi_long len) +{ + abi_long ret; + void *gname = NULL; /* unlocked in cases where set */ + void *gvalue = NULL; /* unlocked in cases where set */ + + ret = -TARGET_EINVAL; + switch (action) { + case KENV_GET: + gname = lock_user_string(name); + if (gname == NULL) { + ret = -TARGET_EFAULT; + break; + } + gvalue = lock_user(VERIFY_WRITE, value, len, 0); + if (gvalue == NULL) { + ret = -TARGET_EFAULT; + break; + } + ret = kenv(action, gname, gvalue, len); + if (ret > 0) { + len = ret; + } + break; + case KENV_SET: + gname = lock_user_string(name); + if (gname == NULL) { + ret = -TARGET_EFAULT; + break; + } + gvalue = lock_user(VERIFY_READ, value, len, 1); + if (gvalue == NULL) { + ret = -TARGET_EFAULT; + break; + } + ret = kenv(action, gname, gvalue, len); + break; + case KENV_UNSET: + gname = lock_user_string(name); + if (gname == NULL) { + ret = -TARGET_EFAULT; + break; + } + /* value and name ignored, per kenv(2) */ + ret = kenv(action, gname, NULL, 0); + break; + /* All three treated the same */ + case KENV_DUMP: + case KENV_DUMP_LOADER: + case KENV_DUMP_STATIC: + /* value == NULL -> just return length */ + if (value != 0) { + gvalue = lock_user(VERIFY_WRITE, value, len, 0); + if (gvalue == NULL) { + ret = -TARGET_EFAULT; + break; + } + } + /* name is ignored, per kenv(2) */ + ret = kenv(action, NULL, gvalue, len); + if (ret > 0) { + len = ret; + } + break; + default: + ret = -TARGET_EINVAL; + break; + } + + /* Unmap everything mapped */ + if (gvalue != NULL) { + unlock_user(gvalue, value, len); + } + if (gname != NULL) { + unlock_user(gname, name, 0); + } + + return ret; +} #endif /* OS_MISC_H */ -- 2.52.0
