diff --git a/repos/libports/lib/mk/libc-gen.inc b/repos/libports/lib/mk/libc-gen.inc index 44a277f938..85fcd6df9a 100644 --- a/repos/libports/lib/mk/libc-gen.inc +++ b/repos/libports/lib/mk/libc-gen.inc @@ -3,6 +3,11 @@ LIBC_GEN_DIR = $(LIBC_DIR)/lib/libc/gen # this file produces a warning about a missing header file, lets drop it FILTER_OUT_C += getosreldate.c sem.c valloc.c getpwent.c +# the following are superceded by our minimalist sysctl and sysconf +FILTER_OUT_C += \ + devname.c feature_present.c getpagesizes.c getvfsbyname.c \ + setproctitle.c sysconf.c sysctlbyname.c + SRC_C = $(filter-out $(FILTER_OUT_C),$(notdir $(wildcard $(LIBC_GEN_DIR)/*.c))) # 'sysconf.c' includes the local 'stdtime/tzfile.h' diff --git a/repos/libports/lib/mk/libc.mk b/repos/libports/lib/mk/libc.mk index f9f347029b..188a0680bf 100644 --- a/repos/libports/lib/mk/libc.mk +++ b/repos/libports/lib/mk/libc.mk @@ -17,6 +17,8 @@ SRC_CC = atexit.cc dummies.cc rlimit.cc sysctl.cc \ libc_pdbg.cc vfs_plugin.cc rtc.cc dynamic_linker.cc signal.cc \ socket_operations.cc task.cc +CC_OPT_sysctl += -Wno-write-strings + INC_DIR += $(REP_DIR)/src/lib/libc INC_DIR += $(REP_DIR)/src/lib/libc/include @@ -31,6 +33,11 @@ SRC_C += strcoll.c strxfrm.c wcscoll.c wcsxfrm.c include $(REP_DIR)/lib/mk/libc-common.inc +# +# Version information for sysctl +# +include $(REP_DIR)/src/lib/libc/version.inc + vpath % $(REP_DIR)/src/lib/libc vpath % $(LIBC_DIR)/lib/libc/string diff --git a/repos/libports/src/lib/libc/fd_alloc.cc b/repos/libports/src/lib/libc/fd_alloc.cc index 44705926cf..de17c51744 100644 --- a/repos/libports/src/lib/libc/fd_alloc.cc +++ b/repos/libports/src/lib/libc/fd_alloc.cc @@ -94,5 +94,4 @@ File_descriptor *File_descriptor_allocator::find_by_libc_fd(int libc_fd) ** Libc functions ** ********************/ -extern "C" int __attribute__((weak)) getdtablesize(void) { - PDBG("libc"); return MAX_NUM_FDS; } +extern "C" int __attribute__((weak)) getdtablesize(void) { return MAX_NUM_FDS; } diff --git a/repos/libports/src/lib/libc/libc_errno.h b/repos/libports/src/lib/libc/libc_errno.h new file mode 100644 index 0000000000..ebb8182b07 --- /dev/null +++ b/repos/libports/src/lib/libc/libc_errno.h @@ -0,0 +1,31 @@ +/* + * \brief C++ wrapper over errno + * \author Christian Helmuth + * \date 2016-04-26 + */ + +/* + * Copyright (C) 2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _LIBC_ERRNO_H_ +#define _LIBC_ERRNO_H_ + +/* libc includes */ +#include + +namespace Libc { struct Errno; } + +struct Libc::Errno +{ + int const error; + + explicit Errno(int error) : error(error) { errno = error; } + + operator int() const { return -1; } +}; + +#endif /* _LIBC_ERRNO_H_ */ diff --git a/repos/libports/src/lib/libc/sysctl.cc b/repos/libports/src/lib/libc/sysctl.cc index 15d78603d9..fc664e7b56 100644 --- a/repos/libports/src/lib/libc/sysctl.cc +++ b/repos/libports/src/lib/libc/sysctl.cc @@ -1,73 +1,266 @@ /* - * \brief C-library back end - * \author Norman Feske - * \date 2008-11-11 + * \brief Sysctl facade + * \author Emery Hemingway + * \date 2016-04-27 */ /* - * Copyright (C) 2008-2013 Genode Labs GmbH + * Copyright (C) 2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#include +/* Genode includes */ +#include +#include -#include +/* Genode-specific libc interfaces */ +#include +#include + +/* Libc includes */ #include #include +#include +#include +#include + +#include "libc_errno.h" + + +enum { PAGESIZE = 4096 }; + + +extern "C" long sysconf(int name) +{ + switch (name) { + case _SC_CHILD_MAX: return CHILD_MAX; + case _SC_OPEN_MAX: return getdtablesize(); + case _SC_NPROCESSORS_CONF: return 1; + case _SC_NPROCESSORS_ONLN: return 1; + case _SC_PAGESIZE: return PAGESIZE; + + case _SC_PHYS_PAGES: + return Genode::env()->ram_session()->quota() / PAGESIZE; + default: + PWRN("%s(%d) not implemented", __func__, name); + return Libc::Errno(EINVAL); + } +} + + +/* non-standard FreeBSD function not supported */ +extern "C" int sysctlbyname(char const *name, void *oldp, size_t *oldlenp, + void *newp, size_t newlen) +{ + PWRN("%s(%s,...) not implemented", __func__, name); + return Libc::Errno(ENOENT); +} -#include "libc_debug.h" extern "C" int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { - int i; - raw_write_str("__sysctl called\n"); + static const ctlname ctl_names[] = CTL_NAMES; + static const ctlname ctl_kern_names[] = CTL_KERN_NAMES; + static const ctlname ctl_hw_names[] = CTL_HW_NAMES; + static const ctlname ctl_user_names[] = CTL_USER_NAMES; + static const ctlname ctl_p1003_1b_names[] = CTL_P1003_1B_NAMES; - /* - * During printf, __sysctl is called by malloc with the parameters - * - * name[0] == 6 (CTL_HW) - * name[1] == 3 (HW_NCPU) - * - * In this case, we can return -1, and the libC assumes that we - * have one CPU. - */ - if ((name[0] == CTL_HW) && (name[1] == HW_NCPU)) - return -1; + /* read only */ + if (!oldp) /* check for write attempt */ + return Libc::Errno(newp ? EPERM : EINVAL); - /* - * CTL_P1003_1B is used by sysconf(_SC_PAGESIZE) to determine - * the actual page size. - */ - if (((name[0] == CTL_HW) && (name[1] == HW_PAGESIZE)) || - ((name[0] == CTL_P1003_1B) && (name[1] == CTL_P1003_1B_PAGESIZE))) { - int result = 4096; - if (oldp) { - if (*oldlenp >= sizeof(result)) { - *(int*)oldp = result; - *oldlenp = sizeof(result); + ctlname const *ctl = nullptr; + char *buf = (char*)oldp; + int index_a = name[0]; + int index_b = name[1]; + + if (namelen != 2) return Libc::Errno(ENOENT); + if (index_a >= CTL_MAXID) return Libc::Errno(EINVAL); + + switch(index_a) { + case CTL_KERN: + if (index_b >= KERN_MAXID) return Libc::Errno(EINVAL); + ctl = &ctl_kern_names[index_b]; break; + + case CTL_HW: + if (index_b >= HW_MAXID) return Libc::Errno(EINVAL); + ctl = &ctl_hw_names[index_b]; break; + + case CTL_USER: + if (index_b >= USER_MAXID) return Libc::Errno(EINVAL); + ctl = &ctl_user_names[index_b]; break; + + case CTL_P1003_1B: + if (index_b >= CTL_P1003_1B_MAXID) return Libc::Errno(EINVAL); + ctl = &ctl_p1003_1b_names[index_b]; break; + } + + if (!ctl) return Libc::Errno(EINVAL); + + if (((ctl->ctl_type == CTLTYPE_INT) && (*oldlenp < sizeof(int))) || + ((ctl->ctl_type == CTLTYPE_STRING) && (*oldlenp < 1)) || + ((ctl->ctl_type == CTLTYPE_QUAD) && (*oldlenp < sizeof(Genode::uint64_t))) || + ((ctl->ctl_type == CTLTYPE_UINT) && (*oldlenp < sizeof(unsigned int))) || + ((ctl->ctl_type == CTLTYPE_LONG) && (*oldlenp < sizeof(long))) || + ((ctl->ctl_type == CTLTYPE_ULONG) && (*oldlenp < sizeof(unsigned long)))) + { + return Libc::Errno(EINVAL); + } + + /* builtins */ + { + switch(index_a) { + case CTL_HW: switch(index_b) { + + case HW_PHYSMEM: + case HW_USERMEM: + *(unsigned long*)oldp = Genode::env()->ram_session()->quota(); + *oldlenp = sizeof(unsigned long); return 0; - } else { - PERR("not enough room to store the old value"); - return -1; - } - } else { - PERR("cannot store the result in oldp, since it is NULL"); - return -1; + + case HW_PAGESIZE: + *(int*)oldp = (int)PAGESIZE; + *oldlenp = sizeof(int); + return 0; + + } break; + + case CTL_P1003_1B: switch(index_b) { + + case CTL_P1003_1B_PAGESIZE: + *(int*)oldp = PAGESIZE; + *oldlenp = sizeof(int); + return 0; + + } break; } } - raw_write_str(newp ? "newp provided\n" : "no newp provided\n"); - for (i = 0; i < name[0]; i++) - raw_write_str("*"); - raw_write_str("\n"); - for (i = 0; i < name[1]; i++) - raw_write_str("%"); - raw_write_str("\n"); + /* runtime overrides */ + { + Libc::Absolute_path sysctl_path(ctl_names[index_a].ctl_name, "/.sysctl/"); + sysctl_path.append("/"); + sysctl_path.append(ctl->ctl_name); - return 0; + /* + * read from /.sysctl/... + * + * The abstracted libc interface is used to read files here + * rather than to explicity resolve a file system plugin. + */ + int fd = open(sysctl_path.base(), 0); + if (fd != -1) { + auto n = read(fd, buf, *oldlenp); + close(fd); + + if (n > 0) switch (ctl->ctl_type) { + case CTLTYPE_INT: { + long value = 0; + Genode::ascii_to((char*)oldp, value); + *(int*)oldp = int(value); + *oldlenp = sizeof(int); + return 0; + } + + case CTLTYPE_STRING: + *oldlenp = n; + return 0; + + case CTLTYPE_QUAD: { + Genode::uint64_t value = 0; + Genode::ascii_to((char*)oldp, value); + *(Genode::uint64_t*)oldp = value; + *oldlenp = sizeof(Genode::uint64_t); + return 0; + } + + case CTLTYPE_UINT: { + unsigned value = 0; + Genode::ascii_to((char*)oldp, value); + *(unsigned*)oldp = value; + *oldlenp = sizeof(unsigned); + return 0; + } + + case CTLTYPE_LONG: { + long value = 0; + Genode::ascii_to((char*)oldp, value); + *(long*)oldp = value; + *oldlenp = sizeof(long); + return 0; + } + + case CTLTYPE_ULONG: { + unsigned long value = 0; + Genode::ascii_to((char*)oldp, value); + *(unsigned long*)oldp = value; + *oldlenp = sizeof(unsigned long); + return 0; + } + + default: + PWRN("unhandled sysctl data type for %s", sysctl_path.base()); + return Libc::Errno(EINVAL); + } + } + } + + + /* fallback values */ + { + switch(index_a) { + + case CTL_KERN: + switch(index_b) { + case KERN_OSTYPE: + Genode::strncpy(buf, "Genode", *oldlenp); + *oldlenp = Genode::strlen(buf); + return 0; + + case KERN_OSRELEASE: + Genode::strncpy(buf, GENODE_OSRELEASE, *oldlenp); + *oldlenp = Genode::strlen(buf); + return 0; + + case KERN_OSREV: + *(int*)oldp = int(GENODE_OSREV); + *oldlenp = sizeof(int); + return 0; + + case KERN_VERSION: + Genode::strncpy(buf, GENODE_VERSION, *oldlenp); + *oldlenp = Genode::strlen(buf); + return 0; + + case KERN_HOSTNAME: + Genode::strncpy(buf, "localhost", *oldlenp); + *oldlenp = Genode::strlen(buf); + return 0; + + } break; + + case CTL_HW: switch(index_b) { + + case HW_MACHINE: + Genode::strncpy(buf, GENODE_MACHINE, *oldlenp); + *oldlenp = Genode::strlen(buf); + return 0; + + case HW_NCPU: + *(int*)oldp = 1; + *oldlenp = sizeof(int); + return 0; + + } break; + + } + } + + PWRN("sysctl: no builtin or override value found for %s.%s", + ctl_names[index_a].ctl_name, ctl->ctl_name); + return Libc::Errno(ENOENT); } - diff --git a/repos/libports/src/lib/libc/version.inc b/repos/libports/src/lib/libc/version.inc new file mode 100644 index 0000000000..27eec8b8ab --- /dev/null +++ b/repos/libports/src/lib/libc/version.inc @@ -0,0 +1,41 @@ +# +# Provide version information to sysctl +# +GENODE_ROOT_DIR = $(REP_DIR)/../.. + +GENODE_OSRELEASE := $(shell cat $(GENODE_ROOT_DIR)/VERSION) + +GENODE_OSREV := $(shell which git > /dev/null && git rev-list --count HEAD) + +GENODE_VERSION := $(shell \ + which git > /dev/null \ + && git -C $(GENODE_ROOT_DIR) describe 2> /dev/null \ + && exit 0 \ + || \ + test -r $(GENODE_ROOT_DIR)/VERSION \ + && cat $(GENODE_ROOT_DIR)/VERSION \ + && exit 0 \ + || \ + echo "") + +CC_OPT += -DGENODE_OSRELEASE="\"$(GENODE_OSRELEASE)\"" +CC_OPT += -DGENODE_OSREV="$(GENODE_OSREV)" +CC_OPT += -DGENODE_VERSION="\"$(GENODE_VERSION)\"" + +ifeq ($(findstring arm, $(SPECS)), arm) +CC_OPT += -DGENODE_MACHINE="\"arm\"" +else +ifeq ($(findstring riscv, $(SPECS)), riscv) +CC_OPT += -DGENODE_MACHINE="\"riscv\"" +else +ifeq ($(findstring x86_32, $(SPECS)), x86_32) +CC_OPT += -DGENODE_MACHINE="\"i686\"" +else +ifeq ($(findstring x86_64, $(SPECS)), x86_64) +CC_OPT += -DGENODE_MACHINE="\"x86_64\"" +else +CC_OPT += -DGENODE_MACHINE="\"unknown\"" +endif +endif +endif +endif diff --git a/repos/ports/run/noux_uname.run b/repos/ports/run/noux_uname.run new file mode 100644 index 0000000000..aaef5b6099 --- /dev/null +++ b/repos/ports/run/noux_uname.run @@ -0,0 +1,76 @@ +build { core init drivers/timer noux/minimal + lib/libc_noux noux-pkg/coreutils } + +# strip coreutils binaries and create tar archive +exec sh -c "[cross_dev_prefix]strip bin/coreutils/bin/*" +exec tar cfv bin/coreutils.tar -h -C bin/coreutils . + +create_boot_directory + +install_config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Muck OS XIII + localhost + + + norisc + + + + + + + + + + + + + + + +} + +build_boot_image { + core init timer ld.lib.so noux libc.lib.so libm.lib.so + libc_noux.lib.so coreutils.tar +} + +append qemu_args " -nographic -serial mon:stdio " + +if {[have_spec x86_64]} { + # coreutils.tar is really huge when built for x86_64 + append qemu_args " -m 300 " +} + +run_genode_until {child "noux" exited with exit value 0.*\n} 30 + +exec rm bin/coreutils.tar