@@ -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 */