xref: /freebsd/stand/kboot/include/host_syscall.h (revision 3ae18fdf)
12b7918f1SWarner Losh /*
22b7918f1SWarner Losh  * Copyright (c) 2022, Netflix, Inc.
32e3f4988SWarner Losh  *
42b7918f1SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
52e3f4988SWarner Losh  *
62b7918f1SWarner Losh  * Rewritten from the original host_syscall.h Copyright (C) 2014 Nathan Whitehorn
72e3f4988SWarner Losh  */
82e3f4988SWarner Losh 
92e3f4988SWarner Losh #ifndef _HOST_SYSCALL_H
102e3f4988SWarner Losh #define _HOST_SYSCALL_H
112e3f4988SWarner Losh 
122e3f4988SWarner Losh #include <stand.h>
132e3f4988SWarner Losh #include <assert.h>
142e3f4988SWarner Losh 
152e3f4988SWarner Losh long host_syscall(int number, ...);
162e3f4988SWarner Losh 
172e3f4988SWarner Losh /*
182e3f4988SWarner Losh  * Sizes taken from musl's include/alltypes.h.in and expanded for LP64 hosts
192e3f4988SWarner Losh  */
202e3f4988SWarner Losh typedef uint64_t host_dev_t;
212e3f4988SWarner Losh typedef uint64_t host_ino_t;
222e3f4988SWarner Losh typedef unsigned int host_mode_t;
232e3f4988SWarner Losh typedef unsigned int host_uid_t;
242e3f4988SWarner Losh typedef unsigned int host_gid_t;
252e3f4988SWarner Losh typedef int64_t host_off_t;
262e3f4988SWarner Losh typedef long host_blksize_t;
272e3f4988SWarner Losh typedef int64_t host_blkcnt_t;
282e3f4988SWarner Losh 
292e3f4988SWarner Losh #include "stat_arch.h"
302e3f4988SWarner Losh 
312e3f4988SWarner Losh /*
322e3f4988SWarner Losh  * stat flags
332e3f4988SWarner Losh  * These are arch independent and match the values in nolib and uapi headers
342e3f4988SWarner Losh  * with HOST_ prepended.
352e3f4988SWarner Losh  */
362e3f4988SWarner Losh #define	HOST_S_IFMT	0170000
372e3f4988SWarner Losh #define	HOST_S_IFIFO	0010000
382e3f4988SWarner Losh #define	HOST_S_IFCHR	0020000
392e3f4988SWarner Losh #define	HOST_S_IFDIR	0040000
402e3f4988SWarner Losh #define	HOST_S_IFBLK	0060000
412e3f4988SWarner Losh #define	HOST_S_IFREG	0100000
422e3f4988SWarner Losh #define	HOST_S_IFLNK	0120000
432e3f4988SWarner Losh #define	HOST_S_IFSOCK	0140000
442e3f4988SWarner Losh 
452e3f4988SWarner Losh #define	HOST_S_ISBLK(mode)	(((mode) & HOST_S_IFMT) == HOST_S_IFBLK)
462e3f4988SWarner Losh #define	HOST_S_ISCHR(mode)	(((mode) & HOST_S_IFMT) == HOST_S_IFCHR)
472e3f4988SWarner Losh #define	HOST_S_ISDIR(mode)	(((mode) & HOST_S_IFMT) == HOST_S_IFDIR)
482e3f4988SWarner Losh #define	HOST_S_ISFIFO(mode)	(((mode) & HOST_S_IFMT) == HOST_S_IFIFO)
492e3f4988SWarner Losh #define	HOST_S_ISLNK(mode)	(((mode) & HOST_S_IFMT) == HOST_S_IFLNK)
502e3f4988SWarner Losh #define	HOST_S_ISREG(mode)	(((mode) & HOST_S_IFMT) == HOST_S_IFREG)
512e3f4988SWarner Losh #define	HOST_S_ISSOCK(mode)	(((mode) & HOST_S_IFMT) == HOST_S_IFSOCK)
522e3f4988SWarner Losh 
532e3f4988SWarner Losh /*
542e3f4988SWarner Losh  * Constants for open, fcntl, etc
552e3f4988SWarner Losh  *
562e3f4988SWarner Losh  * Note: Some of these are arch dependent on Linux, but are the same for
572e3f4988SWarner Losh  * powerpc, x86, arm*, and riscv. We should be futureproof, though, since these
582e3f4988SWarner Losh  * are the 'generic' values and only older architectures (no longer supported by
592e3f4988SWarner Losh  * FreeBSD) vary.
602e3f4988SWarner Losh  *
612e3f4988SWarner Losh  * These are from tools/include/uapi/asm-generic/fcntl.h and use the octal
622e3f4988SWarner Losh  * notation. Beware, hex is used in other places creating potential confsion.
632e3f4988SWarner Losh  */
642e3f4988SWarner Losh #define HOST_O_RDONLY		    0
652e3f4988SWarner Losh #define HOST_O_WRONLY		    1
662e3f4988SWarner Losh #define HOST_O_RDWR		    2
672e3f4988SWarner Losh #define HOST_O_CREAT		00100
682e3f4988SWarner Losh #define HOST_O_EXCL		00200
692e3f4988SWarner Losh #define HOST_O_NOCTTY		00400
702e3f4988SWarner Losh #define HOST_O_TRUNC		01000
712e3f4988SWarner Losh #define HOST_O_APPEND		02000
722e3f4988SWarner Losh #define HOST_O_NONBLOCK		04000
732e3f4988SWarner Losh 
742e3f4988SWarner Losh #define HOST_AT_FDCWD		-100            /* Relative to current directory */
752e3f4988SWarner Losh 
762e3f4988SWarner Losh /*
772e3f4988SWarner Losh  * Data types
782e3f4988SWarner Losh  */
792e3f4988SWarner Losh struct old_utsname {
802e3f4988SWarner Losh 	char sysname[65];
812e3f4988SWarner Losh 	char nodename[65];
822e3f4988SWarner Losh 	char release[65];
832e3f4988SWarner Losh 	char version[65];
842e3f4988SWarner Losh 	char machine[65];
852e3f4988SWarner Losh };
862e3f4988SWarner Losh 
872e3f4988SWarner Losh struct host_timeval {
882e3f4988SWarner Losh 	time_t tv_sec;
892e3f4988SWarner Losh 	long tv_usec;
902e3f4988SWarner Losh };
912e3f4988SWarner Losh 
922e3f4988SWarner Losh /*
932e3f4988SWarner Losh  * Must match Linux's values see linux/tools/include/uapi/asm-generic/mman-common.h
942e3f4988SWarner Losh  * and linux/tools/include/linux/mman.h
952e3f4988SWarner Losh  *
962e3f4988SWarner Losh  * And pre-pend HOST_ here.
972e3f4988SWarner Losh  */
982e3f4988SWarner Losh #define HOST_PROT_READ	0x1
992e3f4988SWarner Losh #define HOST_PROT_WRITE	0x2
1002e3f4988SWarner Losh #define HOST_PROT_EXEC	0x4
1012e3f4988SWarner Losh 
1022e3f4988SWarner Losh #define HOST_MAP_SHARED		0x01
1032e3f4988SWarner Losh #define	HOST_MAP_PRIVATE	0x02
1042e3f4988SWarner Losh #define HOST_MAP_FIXED		0x10
1052e3f4988SWarner Losh #define HOST_MAP_ANONYMOUS	0x20
1062e3f4988SWarner Losh 
1072e3f4988SWarner Losh #define HOST_MAP_FAILED		((void *)-1)
1082e3f4988SWarner Losh 
1092e3f4988SWarner Losh /* Mount flags from uapi */
1102e3f4988SWarner Losh #define MS_RELATIME (1 << 21)
1112e3f4988SWarner Losh 
1122e3f4988SWarner Losh #define HOST_REBOOT_MAGIC1	0xfee1dead
1132e3f4988SWarner Losh #define HOST_REBOOT_MAGIC2	672274793
1142e3f4988SWarner Losh #define HOST_REBOOT_CMD_KEXEC	0x45584543
1152e3f4988SWarner Losh 
1162e3f4988SWarner Losh /*
1172e3f4988SWarner Losh  * Values from linux/tools/include/uapi/linux/kexec.h
1182e3f4988SWarner Losh  */
1192e3f4988SWarner Losh 
1202e3f4988SWarner Losh /*
1212e3f4988SWarner Losh  * Values match ELF architecture types.
1222e3f4988SWarner Losh  */
1232e3f4988SWarner Losh #define HOST_KEXEC_ARCH_X86_64  (62 << 16)
1242e3f4988SWarner Losh #define HOST_KEXEC_ARCH_PPC64   (21 << 16)
1252e3f4988SWarner Losh #define HOST_KEXEC_ARCH_ARM     (40 << 16)
1262e3f4988SWarner Losh #define HOST_KEXEC_ARCH_AARCH64 (183 << 16)
1272e3f4988SWarner Losh #define HOST_KEXEC_ARCH_RISCV   (243 << 16)
1282e3f4988SWarner Losh 
1292e3f4988SWarner Losh /* Arbitrary cap on segments */
1302e3f4988SWarner Losh #define HOST_KEXEC_SEGMENT_MAX 16
1312e3f4988SWarner Losh 
1322e3f4988SWarner Losh struct host_kexec_segment {
1332e3f4988SWarner Losh 	void *buf;
1342e3f4988SWarner Losh 	int bufsz;
1352e3f4988SWarner Losh 	void *mem;
1362e3f4988SWarner Losh 	int memsz;
1372e3f4988SWarner Losh };
1382e3f4988SWarner Losh 
1392e3f4988SWarner Losh struct host_dirent64 {
1402e3f4988SWarner Losh 	uint64_t	d_ino;		/* 64-bit inode number */
1412e3f4988SWarner Losh 	int64_t		d_off;		/* 64-bit offset to next structure */
1422e3f4988SWarner Losh 	unsigned short	d_reclen;	/* Size of this dirent */
1432e3f4988SWarner Losh 	unsigned char	d_type;		/* File type */
1442e3f4988SWarner Losh 	char		d_name[];	/* Filename (null-terminated) */
1452e3f4988SWarner Losh };
1462e3f4988SWarner Losh 
1472e3f4988SWarner Losh /* d_type values */
1482e3f4988SWarner Losh #define HOST_DT_UNKNOWN		 0
1492e3f4988SWarner Losh #define HOST_DT_FIFO		 1
1502e3f4988SWarner Losh #define HOST_DT_CHR		 2
1512e3f4988SWarner Losh #define HOST_DT_DIR		 4
1522e3f4988SWarner Losh #define HOST_DT_BLK		 6
1532e3f4988SWarner Losh #define HOST_DT_REG		 8
1542e3f4988SWarner Losh #define HOST_DT_LNK		10
1552e3f4988SWarner Losh #define HOST_DT_SOCK		12
1562e3f4988SWarner Losh #define HOST_DT_WHT		14
1572e3f4988SWarner Losh 
1582e3f4988SWarner Losh /*
1592e3f4988SWarner Losh  * System Calls
1602e3f4988SWarner Losh  */
1612e3f4988SWarner Losh int host_close(int fd);
1622e3f4988SWarner Losh int host_dup(int fd);
1632e3f4988SWarner Losh int host_exit(int code);
1642e3f4988SWarner Losh int host_fstat(int fd, struct host_kstat *sb);
1652e3f4988SWarner Losh int host_getdents64(int fd, void *dirp, int count);
1662e3f4988SWarner Losh int host_getpid(void);
1672e3f4988SWarner Losh int host_gettimeofday(struct host_timeval *a, void *b);
1682e3f4988SWarner Losh int host_ioctl(int fd, unsigned long request, unsigned long arg);
1692e3f4988SWarner Losh int host_kexec_load(unsigned long entry, unsigned long nsegs, struct host_kexec_segment *segs, unsigned long flags);
1702e3f4988SWarner Losh ssize_t host_llseek(int fd, int32_t offset_high, int32_t offset_lo, uint64_t *result, int whence);
1712e3f4988SWarner Losh int host_mkdir(const char *, host_mode_t);
1722e3f4988SWarner Losh void *host_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off);
1732e3f4988SWarner Losh int host_mount(const char *src, const char *target, const char *type,
1742e3f4988SWarner Losh     unsigned long flags, void *data);
1752e3f4988SWarner Losh int host_munmap(void *addr, size_t len);
1762e3f4988SWarner Losh int host_open(const char *path, int flags, int mode);
1772e3f4988SWarner Losh ssize_t host_read(int fd, void *buf, size_t nbyte);
1782e3f4988SWarner Losh int host_reboot(int, int, int, uintptr_t);
1792e3f4988SWarner Losh int host_select(int nfds, long *readfds, long *writefds, long *exceptfds,
1802e3f4988SWarner Losh     struct host_timeval *timeout);
1812e3f4988SWarner Losh int host_stat(const char *path, struct host_kstat *sb);
1822e3f4988SWarner Losh int host_symlink(const char *path1, const char *path2);
1832e3f4988SWarner Losh int host_uname(struct old_utsname *);
1842e3f4988SWarner Losh ssize_t host_write(int fd, const void *buf, size_t nbyte);
1852e3f4988SWarner Losh 
1862e3f4988SWarner Losh /*
1872e3f4988SWarner Losh  * Wrappers / one-liners
1882e3f4988SWarner Losh  */
1892e3f4988SWarner Losh #define host_getmem(size) \
1902e3f4988SWarner Losh 	host_mmap(0, size, HOST_PROT_READ | HOST_PROT_WRITE, \
1912e3f4988SWarner Losh 	    HOST_MAP_PRIVATE | HOST_MAP_ANONYMOUS, -1, 0);
1922e3f4988SWarner Losh 
1932e3f4988SWarner Losh /*
1943ae18fdfSWarner Losh  * Since we have to interface with the 'raw' system call, we have to cope with
1953ae18fdfSWarner Losh  * Linux's conventions. To run on the most architectures possible, they don't
1963ae18fdfSWarner Losh  * return errors through some CPU flag, but instead, return a negative value for
1973ae18fdfSWarner Losh  * an error, and a positive one for success. However, there's some issues since
1983ae18fdfSWarner Losh  * addresses have to be returned, some of which are also negative, so Linus
1993ae18fdfSWarner Losh  * declared that no successful result could be -4096 to 0. This implements
2003ae18fdfSWarner Losh  * that quirk so we can check return values easily.
2013ae18fdfSWarner Losh  */
2023ae18fdfSWarner Losh static __inline bool
is_linux_error(long e)2033ae18fdfSWarner Losh is_linux_error(long e)
2043ae18fdfSWarner Losh {
2053ae18fdfSWarner Losh 	return (e < 0 && e >= -4096);
2063ae18fdfSWarner Losh }
2073ae18fdfSWarner Losh 
2083ae18fdfSWarner Losh /*
2092e3f4988SWarner Losh  * Translate Linux errno to FreeBSD errno. The two system have idenitcal errors
2102e3f4988SWarner Losh  * for 1-34. After that, they differ. Linux also has errno that don't map
2112e3f4988SWarner Losh  * exactly to FreeBSD's errno, plus the Linux errno are arch dependent >
2122e3f4988SWarner Losh  * 34. Since we just need to do this for simple cases, use the simple mapping
2132e3f4988SWarner Losh  * function where -1 to -34 are translated to 1 to 34 and all others are EINVAL.
2143ae18fdfSWarner Losh  * Pass the linux return value, which will be the -errno. Linux returns these
2153ae18fdfSWarner Losh  * values as a 'long' which has to align to CPU register size, so accept that
2163ae18fdfSWarner Losh  * size as the error so the assert can catch more values.
2172e3f4988SWarner Losh  */
2182e3f4988SWarner Losh static __inline int
host_to_stand_errno(long e)2193ae18fdfSWarner Losh host_to_stand_errno(long e)
2202e3f4988SWarner Losh {
2213ae18fdfSWarner Losh 	assert(is_linux_error(e));
2222e3f4988SWarner Losh 
2232e3f4988SWarner Losh 	return((-e) > 34 ? EINVAL : (-e));
2242e3f4988SWarner Losh }
2252e3f4988SWarner Losh #endif
226