diff --git a/stand/kboot/arch/amd64/syscall_nr.h b/stand/kboot/arch/amd64/syscall_nr.h index 4d8db2083ebc..71930001c1cf 100644 --- a/stand/kboot/arch/amd64/syscall_nr.h +++ b/stand/kboot/arch/amd64/syscall_nr.h @@ -1,20 +1,20 @@ #define SYS_close 3 #define SYS_dup 32 -#define SYS_getdents 78 +#define SYS_getdents64 217 #define SYS_getpid 39 #define SYS_gettimeofday 96 #define SYS_kexec_load 246 #define SYS_lseek 8 #define SYS_mkdirat 258 #define SYS_mmap 9 #define SYS_mount 165 #define SYS_munmap 11 #define SYS_newfstat 5 #define SYS_newfstatat 262 #define SYS_openat 257 #define SYS_pselect6 270 #define SYS_read 0 #define SYS_reboot 169 #define SYS_symlinkat 266 #define SYS_uname 63 #define SYS_write 1 diff --git a/stand/kboot/arch/powerpc64/syscall_nr.h b/stand/kboot/arch/powerpc64/syscall_nr.h index a467259e8b60..0702673c7228 100644 --- a/stand/kboot/arch/powerpc64/syscall_nr.h +++ b/stand/kboot/arch/powerpc64/syscall_nr.h @@ -1,21 +1,21 @@ #define SYS_close 6 #define SYS_dup 41 #define SYS_fstat 108 -#define SYS_getdents 141 +#define SYS_getdents64 202 #define SYS_getpid 20 #define SYS_gettimeofday 78 #define SYS_kexec_load 268 #define SYS_llseek 140 #define SYS_mkdirat 287 #define SYS_mmap 90 #define SYS_mount 21 #define SYS_munmap 91 #define SYS_newfstat SYS_fstat #define SYS_newfstatat 291 #define SYS_openat 286 #define SYS_pselect6 280 #define SYS_read 3 #define SYS_reboot 88 #define SYS_symlinkat 295 #define SYS_uname 120 #define SYS_write 4 diff --git a/stand/kboot/host_syscall.h b/stand/kboot/host_syscall.h index b867cd9f0d99..9f876952641e 100644 --- a/stand/kboot/host_syscall.h +++ b/stand/kboot/host_syscall.h @@ -1,167 +1,186 @@ /*- * Copyright (C) 2014 Nathan Whitehorn * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _HOST_SYSCALL_H #define _HOST_SYSCALL_H #include long host_syscall(int number, ...); /* * Sizes taken from musl's include/alltypes.h.in and expanded for LP64 hosts */ typedef uint64_t host_dev_t; typedef uint64_t host_ino_t; typedef int64_t host_nlink_t; typedef unsigned int host_mode_t; typedef unsigned int host_uid_t; typedef unsigned int host_gid_t; typedef int64_t host_off_t; typedef long host_blksize_t; typedef int64_t host_blkcnt_t; #include "stat_arch.h" /* * Constants for open, fcntl, etc * * Note: Some of these are arch dependent on Linux, but are the same for * powerpc, x86, arm*, and riscv. We should be futureproof, though, since these * are the 'generic' values and only older architectures (no longer supported by * FreeBSD) vary. * * These are from tools/include/uapi/asm-generic/fcntl.h and use the octal * notation. Beware, hex is used in other places creating potential confsion. */ #define HOST_O_RDONLY 0 #define HOST_O_WRONLY 1 #define HOST_O_RDWR 2 #define HOST_O_CREAT 00100 #define HOST_O_EXCL 00200 #define HOST_O_NOCTTY 00400 #define HOST_O_TRUNC 01000 #define HOST_O_APPEND 02000 #define HOST_O_NONBLOCK 04000 #define HOST_AT_FDCWD -100 /* Relative to current directory */ /* * Data types */ struct old_utsname { char sysname[65]; char nodename[65]; char release[65]; char version[65]; char machine[65]; }; struct host_timeval { time_t tv_sec; long tv_usec; }; /* * Must match Linux's values see linux/tools/include/uapi/asm-generic/mman-common.h * and linux/tools/include/linux/mman.h * * And pre-pend HOST_ here. */ #define HOST_PROT_READ 0x1 #define HOST_PROT_WRITE 0x2 #define HOST_PROT_EXEC 0x4 #define HOST_MAP_SHARED 0x01 #define HOST_MAP_PRIVATE 0x02 #define HOST_MAP_FIXED 0x10 #define HOST_MAP_ANONYMOUS 0x20 /* Mount flags from uapi */ #define MS_RELATIME (1 << 21) #define HOST_REBOOT_MAGIC1 0xfee1dead #define HOST_REBOOT_MAGIC2 672274793 #define HOST_REBOOT_CMD_KEXEC 0x45584543 /* * Values from linux/tools/include/uapi/linux/kexec.h */ /* * Values match ELF architecture types. */ #define HOST_KEXEC_ARCH_X86_64 (62 << 16) #define HOST_KEXEC_ARCH_PPC64 (21 << 16) #define HOST_KEXEC_ARCH_ARM (40 << 16) #define HOST_KEXEC_ARCH_AARCH64 (183 << 16) #define HOST_KEXEC_ARCH_RISCV (243 << 16) /* Arbitrary cap on segments */ #define HOST_KEXEC_SEGMENT_MAX 16 struct host_kexec_segment { void *buf; int bufsz; void *mem; int memsz; }; +struct host_dirent64 { + uint64_t d_ino; /* 64-bit inode number */ + int64_t d_off; /* 64-bit offset to next structure */ + unsigned short d_reclen; /* Size of this dirent */ + unsigned char d_type; /* File type */ + char d_name[]; /* Filename (null-terminated) */ +}; + +/* d_type values */ +#define HOST_DT_UNKNOWN 0 +#define HOST_DT_FIFO 1 +#define HOST_DT_CHR 2 +#define HOST_DT_DIR 4 +#define HOST_DT_BLK 6 +#define HOST_DT_REG 8 +#define HOST_DT_LNK 10 +#define HOST_DT_SOCK 12 +#define HOST_DT_WHT 14 + /* * System Calls */ int host_close(int fd); int host_dup(int fd); int host_fstat(int fd, struct host_kstat *sb); -int host_getdents(int fd, void *dirp, int count); +int host_getdents64(int fd, void *dirp, int count); int host_getpid(void); int host_gettimeofday(struct host_timeval *a, void *b); int host_kexec_load(unsigned long entry, unsigned long nsegs, struct host_kexec_segment *segs, unsigned long flags); ssize_t host_llseek(int fd, int32_t offset_high, int32_t offset_lo, uint64_t *result, int whence); int host_mkdir(const char *, host_mode_t); void *host_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off); int host_mount(const char *src, const char *target, const char *type, unsigned long flags, void *data); int host_munmap(void *addr, size_t len); int host_open(const char *path, int flags, int mode); ssize_t host_read(int fd, void *buf, size_t nbyte); int host_reboot(int, int, int, uintptr_t); int host_select(int nfds, long *readfds, long *writefds, long *exceptfds, struct host_timeval *timeout); int host_stat(const char *path, struct host_kstat *sb); int host_symlink(const char *path1, const char *path2); int host_uname(struct old_utsname *); ssize_t host_write(int fd, const void *buf, size_t nbyte); /* * Wrappers / one-liners */ #define host_getmem(size) \ host_mmap(0, size, HOST_PROT_READ | HOST_PROT_WRITE, \ HOST_MAP_PRIVATE | HOST_MAP_ANONYMOUS, -1, 0); #endif diff --git a/stand/kboot/host_syscalls.c b/stand/kboot/host_syscalls.c index 865107263d7b..771f9e128fdd 100644 --- a/stand/kboot/host_syscalls.c +++ b/stand/kboot/host_syscalls.c @@ -1,148 +1,148 @@ #include "host_syscall.h" #include "syscall_nr.h" #include /* * Various trivial wrappers for Linux system calls. Please keep sorted * alphabetically. */ int host_close(int fd) { return host_syscall(SYS_close, fd); } int host_dup(int fd) { return host_syscall(SYS_dup, fd); } int host_fstat(int fd, struct host_kstat *sb) { return host_syscall(SYS_newfstat, fd, (uintptr_t)sb); } int -host_getdents(int fd, void *dirp, int count) +host_getdents64(int fd, void *dirp, int count) { - return host_syscall(SYS_getdents, fd, (uintptr_t)dirp, count); + return host_syscall(SYS_getdents64, fd, (uintptr_t)dirp, count); } int host_getpid(void) { return host_syscall(SYS_getpid); } int host_gettimeofday(struct host_timeval *a, void *b) { return host_syscall(SYS_gettimeofday, (uintptr_t)a, (uintptr_t)b); } int host_kexec_load(unsigned long entry, unsigned long nsegs, struct host_kexec_segment *segs, unsigned long flags) { return host_syscall(SYS_kexec_load, entry, nsegs, segs, flags); } ssize_t host_llseek(int fd, int32_t offset_high, int32_t offset_lo, uint64_t *result, int whence) { #ifdef SYS_llseek return host_syscall(SYS_llseek, fd, offset_high, offset_lo, (uintptr_t)result, whence); #else int64_t rv = host_syscall(SYS_lseek, fd, (int64_t)((uint64_t)offset_high << 32 | (uint32_t)offset_lo), whence); if (rv > 0) *result = (uint64_t)rv; return (rv); #endif } int host_mkdir(const char *path, host_mode_t mode) { return host_syscall(SYS_mkdirat, HOST_AT_FDCWD, (uintptr_t)path, mode); } void * host_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off) { return (void *)host_syscall(SYS_mmap, (uintptr_t)addr, len, prot, flags, fd, off); } int host_mount(const char *src, const char *target, const char *type, unsigned long flags, void *data) { return host_syscall(SYS_mount, src, target, type, flags, data); } int host_munmap(void *addr, size_t len) { return host_syscall(SYS_munmap, (uintptr_t)addr, len); } int host_open(const char *path, int flags, int mode) { return host_syscall(SYS_openat, HOST_AT_FDCWD, (uintptr_t)path, flags, mode); /* XXX original overrode errors */ } ssize_t host_read(int fd, void *buf, size_t nbyte) { return host_syscall(SYS_read, fd, (uintptr_t)buf, nbyte); /* XXX original overrode errors */ } int host_reboot(int magic1, int magic2, int cmd, uintptr_t arg) { return host_syscall(SYS_reboot, magic1, magic2, cmd, arg); } int host_select(int nfds, long *readfds, long *writefds, long *exceptfds, struct host_timeval *timeout) { struct timespec ts = { .tv_sec = timeout->tv_sec, .tv_nsec = timeout->tv_usec * 1000 }; /* * Note, final arg is a sigset_argpack since most arch can only have 6 * syscall args. Since we're not masking signals, though, we can just * pass a NULL. */ return host_syscall(SYS_pselect6, nfds, (uintptr_t)readfds, (uintptr_t)writefds, (uintptr_t)exceptfds, (uintptr_t)&ts, (uintptr_t)NULL); } int host_stat(const char *path, struct host_kstat *sb) { return host_syscall(SYS_newfstatat, HOST_AT_FDCWD, (uintptr_t)path, (uintptr_t)sb, 0); } int host_symlink(const char *path1, const char *path2) { return host_syscall(SYS_symlinkat, HOST_AT_FDCWD, path1, path2); } int host_uname(struct old_utsname *uts) { return host_syscall(SYS_uname, (uintptr_t)uts); } ssize_t host_write(int fd, const void *buf, size_t nbyte) { return host_syscall(SYS_write, fd, (uintptr_t)buf, nbyte); } diff --git a/stand/kboot/kbootfdt.c b/stand/kboot/kbootfdt.c index 5e0ef9ea3068..e4e8e7cfbf04 100644 --- a/stand/kboot/kbootfdt.c +++ b/stand/kboot/kbootfdt.c @@ -1,190 +1,182 @@ /*- * Copyright (C) 2014 Nathan Whitehorn * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include "bootstrap.h" #include "host_syscall.h" static void add_node_to_fdt(void *buffer, const char *path, int fdt_offset) { int child_offset, fd, pfd, error, dentsize; char subpath[512]; void *propbuf; ssize_t proplen; - struct host_dent { - unsigned long d_fileno; - unsigned long d_off; - unsigned short d_reclen; - char d_name[]; - /* uint8_t d_type; */ - }; char dents[2048]; - struct host_dent *dent; + struct host_dirent64 *dent; int d_type; fd = host_open(path, O_RDONLY, 0); while (1) { - dentsize = host_getdents(fd, dents, sizeof(dents)); + dentsize = host_getdents64(fd, dents, sizeof(dents)); if (dentsize <= 0) break; - for (dent = (struct host_dent *)dents; + for (dent = (struct host_dirent64 *)dents; (char *)dent < dents + dentsize; - dent = (struct host_dent *)((void *)dent + dent->d_reclen)) { + dent = (struct host_dirent64 *)((void *)dent + dent->d_reclen)) { sprintf(subpath, "%s/%s", path, dent->d_name); if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) continue; - d_type = *((char *)(dent) + dent->d_reclen - 1); + d_type = dent->d_type; if (d_type == 4 /* DT_DIR */) { child_offset = fdt_add_subnode(buffer, fdt_offset, dent->d_name); if (child_offset < 0) { printf("Error %d adding node %s/%s, skipping\n", child_offset, path, dent->d_name); continue; } - add_node_to_fdt(buffer, subpath, child_offset); } else { propbuf = malloc(1024); proplen = 0; pfd = host_open(subpath, O_RDONLY, 0); if (pfd > 0) { proplen = host_read(pfd, propbuf, 1024); host_close(pfd); } error = fdt_setprop(buffer, fdt_offset, dent->d_name, propbuf, proplen); free(propbuf); if (error) printf("Error %d adding property %s to " "node %d\n", error, dent->d_name, fdt_offset); } } } host_close(fd); } /* Fix up wrong values added to the device tree by prom_init() in Linux */ static void fdt_linux_fixups(void *fdtp) { int offset, len; const void *prop; /* * Remove /memory/available properties, which reflect long-gone OF * state */ offset = fdt_path_offset(fdtp, "/memory@0"); if (offset > 0) fdt_delprop(fdtp, offset, "available"); /* * Add reservations for OPAL and RTAS state if present */ offset = fdt_path_offset(fdtp, "/ibm,opal"); if (offset > 0) { const uint64_t *base, *size; base = fdt_getprop(fdtp, offset, "opal-base-address", &len); size = fdt_getprop(fdtp, offset, "opal-runtime-size", &len); if (base != NULL && size != NULL) fdt_add_mem_rsv(fdtp, fdt64_to_cpu(*base), fdt64_to_cpu(*size)); } offset = fdt_path_offset(fdtp, "/rtas"); if (offset > 0) { const uint32_t *base, *size; base = fdt_getprop(fdtp, offset, "linux,rtas-base", &len); size = fdt_getprop(fdtp, offset, "rtas-size", &len); if (base != NULL && size != NULL) fdt_add_mem_rsv(fdtp, fdt32_to_cpu(*base), fdt32_to_cpu(*size)); } /* * Patch up /chosen nodes so that the stored handles mean something, * where possible. */ offset = fdt_path_offset(fdtp, "/chosen"); if (offset > 0) { fdt_delprop(fdtp, offset, "cpu"); /* This node not meaningful */ offset = fdt_path_offset(fdtp, "/chosen"); prop = fdt_getprop(fdtp, offset, "linux,stdout-package", &len); if (prop != NULL) { fdt_setprop(fdtp, offset, "stdout", prop, len); offset = fdt_path_offset(fdtp, "/chosen"); fdt_setprop(fdtp, offset, "stdin", prop, len); } } } int fdt_platform_load_dtb(void) { void *buffer; size_t buflen = 409600; buffer = malloc(buflen); fdt_create_empty_tree(buffer, buflen); add_node_to_fdt(buffer, "/proc/device-tree", fdt_path_offset(buffer, "/")); fdt_linux_fixups(buffer); fdt_pack(buffer); fdt_load_dtb_addr(buffer); free(buffer); return (0); } void fdt_platform_load_overlays(void) { } void fdt_platform_fixups(void) { }