From 4d3da263a9c35208ef32f0fef956d120fb2e6e14 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Mon, 7 Jan 2019 14:18:46 +1100 Subject: Add a libbsd dynamically loaded application. --- libbsd/libdl/dl_libbsd.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++ libbsd/libdl/dl_main.c | 178 +++++++++++++++++++++++++++++++++++++++++++++ libbsd/libdl/libdl.conf | 2 + libbsd/libdl/wscript | 126 ++++++++++++++++++++++++++++++++ libbsd/wscript | 14 ++++ wscript | 9 ++- 6 files changed, 513 insertions(+), 1 deletion(-) create mode 100644 libbsd/libdl/dl_libbsd.c create mode 100644 libbsd/libdl/dl_main.c create mode 100644 libbsd/libdl/libdl.conf create mode 100644 libbsd/libdl/wscript create mode 100644 libbsd/wscript diff --git a/libbsd/libdl/dl_libbsd.c b/libbsd/libdl/dl_libbsd.c new file mode 100644 index 0000000..71a1c7b --- /dev/null +++ b/libbsd/libdl/dl_libbsd.c @@ -0,0 +1,185 @@ +/* + * Copyright 2018 Chris Johns + * + * 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 AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#define IFACE_IPV4(iface) \ + "ifconfig_" # iface "=\"inet " NET_CFG_SELF_IP " netmask " NET_CFG_NETMASK "\"\n" + +#define IFACE_ALIAS(iface) \ + "ifconfig_" # iface "_alias0=\"ether 10:22:33:44:55:66\"\n" \ + "ifconfig_" # iface "_alias1=\"inet 10.1.1.111 netmask 0xffffffff\"\n" + +#define RC_CONF_IFACES_IPV4 \ + IFACE_IPV4(dmc0) \ + IFACE_IPV4(sm0) \ + IFACE_IPV4(cgem0) \ + IFACE_IPV4(fec0) \ + IFACE_IPV4(em0) \ + IFACE_IPV4(re0) + +#define RC_CONF_IFACES_ALIAS \ + IFACE_ALIAS(dmc0) \ + IFACE_ALIAS(sm0) \ + IFACE_ALIAS(cgem0) \ + IFACE_ALIAS(fec0) \ + IFACE_ALIAS(em0) \ + IFACE_ALIAS(re0) + +#define RC_CONF_IFACES \ + RC_CONF_IFACES_IPV4 \ + RC_CONF_IFACES_ALIAS + +#define IFACE_VLAN(iface) \ + "vlans_" # iface "=\"101 102\"\n" \ + "ifconfig_" # iface "_101=\"inet 192.0.101.1/24\"\n" \ + "ifconfig_" # iface "_102=\"DHCP\"\n" + +#define RC_CONF_VLANS \ + IFACE_VLAN(dmc0) \ + IFACE_VLAN(sm0) \ + IFACE_VLAN(cgem0) \ + IFACE_VLAN(fec0) \ + IFACE_VLAN(em0) \ + IFACE_VLAN(re0) + +static const char* rc_conf_text = \ + "#\n" \ + "# Tests rc.conf. Add every NIC\n" \ + "#\n" \ + "\n" \ + "syslog_priority=\"debug\"\n" \ + "\n" \ + "hostname=\"rctest\"\n" \ + "\n" \ + "create_args_myvlan=\"vlan 102\"\n" \ + "create_args_yourvlan=\"vlan 202\"\n" \ + "\n" \ + RC_CONF_IFACES \ + "\n" \ + RC_CONF_VLANS \ + "\n" \ + "defaultrouter=\"" NET_CFG_GATEWAY_IP "\"\n" \ + "defaultroute_delay=\"5\"\n" \ + "\n" \ + "dhcpcd_options=\"-h foobar\"\n" \ + "\n" \ + "telnetd_enable=\"YES\"\n" \ + "telnetd_options=\"-v -C 10 -P 50 -L\"\n" \ + "\n" \ + "ftpd_enable=\"YES\"\n" \ + "ftpd_options=\"-v -p 21 -C 10 -P 150 -L -I 10 -R /\"\n" \ + "\n" \ + "pf_enable=\"YES\"\n" \ + "pf_rules=\"/etc/mypf.conf\"\n" \ + "pf_flags=\"-q -z\"\n" \ + "\n"; + +static const char* pf_conf_text = "pass all\n"; +static const char* pf_os_text = "# empty\n"; + +static void +test_rc_conf_script(void) +{ + const char* ifconfg_args[] = { + "ifconfig", NULL + }; + const char* netstat_args[] = { + "netstat", "-rn", NULL + }; + const char* pfctl_args[] = { + "pfctl", "-s", "rules", NULL + }; + + printf("--------------- rc.conf -----------------\n"); + printf(rc_conf_text); + printf("-----------------------------------------\n"); + + assert(rtems_bsd_run_rc_conf_script("internal", rc_conf_text, 15, true) == 0); + + printf("-------------- IFCONFIG -----------------\n"); + rtems_bsd_command_ifconfig(1, (char**) ifconfg_args); + printf("-------------- NETSTAT ------------------\n"); + rtems_bsd_command_netstat(2, (char**) netstat_args); + printf("-------------- PFCTL --------------------\n"); + rtems_bsd_command_pfctl(RTEMS_BSD_ARGC(pfctl_args), (char **) pfctl_args); + printf("-----------------------------------------\n"); +} + +static void +waiter(int fd, int secs, void *arg) +{ + int* toggle = (int*) arg; + const char* toggles = "|/-|\\-"; + printf("\b%c", toggles[*toggle]); + fflush(stdout); + ++(*toggle); + if (*toggle >= 6) + *toggle = 0; +} + +static void +shell(void) +{ + int toggle = 1; + rtems_status_code sc; + printf("Press any key for the shell .... -"); + fflush(stdout); + sc = rtems_shell_wait_for_input(STDIN_FILENO, 10, waiter, &toggle); + if (sc == RTEMS_SUCCESSFUL) { + rtems_shell_init("SHLL", + 32 * 1024, + 1, + CONSOLE_DEVICE_NAME, + false, + true, + NULL); + } +} + +void +rtems_main(void) +{ + test_rc_conf_script(); + shell(); +} diff --git a/libbsd/libdl/dl_main.c b/libbsd/libdl/dl_main.c new file mode 100644 index 0000000..70e23fe --- /dev/null +++ b/libbsd/libdl/dl_main.c @@ -0,0 +1,178 @@ +/* + * Copyright 2018 Chris Johns + * + * 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 AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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 + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "libbsd-dl-rootfs-tar.h" + +#define EXAMPLE_NAME "LIBBSD LIBDL 1" + +#define ARCHIVE_TRACE (RTEMS_RTL_TRACE_DETAIL | \ + RTEMS_RTL_TRACE_WARNING | \ + RTEMS_RTL_TRACE_LOAD | \ + RTEMS_RTL_TRACE_UNLOAD | \ + RTEMS_RTL_TRACE_SYMBOL | \ + RTEMS_RTL_TRACE_RELOC | \ + RTEMS_RTL_TRACE_ALLOCATOR | \ + RTEMS_RTL_TRACE_UNRESOLVED | \ + RTEMS_RTL_TRACE_ARCHIVES | \ + RTEMS_RTL_TRACE_DEPENDENCY) +#define EXAMPLE_DEBUG_TRACE ARCHIVE_TRACE + +#define TARFILE_START libbsd_dl_rootfs_tar +#define TARFILE_SIZE libbsd_dl_rootfs_tar_size + +typedef int (*call_sig)(void); + +static void +dl_load_dump (void) +{ +#if LIBDL01_CMDS + char* list[] = { "rtl", "list", NULL }; + char* sym[] = { "rtl", "sym", NULL }; + printf ("RTL List:\n"); + rtems_rtl_shell_command (2, list); + printf ("RTL Sym:\n"); + rtems_rtl_shell_command (2, sym); +#endif +} + +static void +example_fatal_error (void) +{ + rtems_status_code sc = rtems_task_wake_after( 3 ); + assert(sc == RTEMS_SUCCESSFUL); + assert( 0 ); +} + +rtems_task Init( + rtems_task_argument ignored +) +{ + const char* name = "dl_libbsd.o"; + void* handle; + int unresolved = 0; + call_sig call; + int te; + + puts( "\n\nExample: " EXAMPLE_NAME ); + + te = Untar_FromMemory((void *)TARFILE_START, (size_t)TARFILE_SIZE); + if (te != 0) + { + printf("untar failed: %d\n", te); + example_fatal_error(); + } + +#if EXAMPLE_DEBUG_TRACE + rtems_rtl_trace_set_mask (EXAMPLE_DEBUG_TRACE); +#endif + + printf("load: %s\n", name); + + handle = dlopen (name, RTLD_NOW | RTLD_GLOBAL); + if (handle == NULL) + { + printf("error: loading %s failed: %s\n", name, dlerror ()); + example_fatal_error (); + } + + printf ("handle: %p loaded\n", handle); + + if (dlinfo (handle, RTLD_DI_UNRESOLVED, &unresolved) != 0) + { + printf ("error: cannot get module's unresolved status\n"); + example_fatal_error (); + } + + printf ("unresolved: %p: %s \n", handle, unresolved == 0 ? "resolved" : "UNRESOLVED"); + + if (unresolved != 0) + { + printf ("error: module has unresolved externals\n"); + example_fatal_error (); + } + + call = dlsym (handle, "rtems_main"); + if (call == NULL) + { + printf ("error: cannot find symbol: rtems_main\n"); + example_fatal_error (); + } + + call (); + + if (dlclose (handle) != 0) + { + printf ("error: unloading %s failed: %d\n", name, dlerror ()); + example_fatal_error (); + } +} + +/* + * Configure RTEMS. + */ +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_ZERO_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK + +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 32 + +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 + +#define CONFIGURE_UNLIMITED_ALLOCATION_SIZE 32 +#define CONFIGURE_UNLIMITED_OBJECTS +#define CONFIGURE_UNIFIED_WORK_AREAS + +#define CONFIGURE_STACK_CHECKER_ENABLED + +#define CONFIGURE_BDBUF_BUFFER_MAX_SIZE (64 * 1024) +#define CONFIGURE_BDBUF_MAX_READ_AHEAD_BLOCKS 4 +#define CONFIGURE_BDBUF_CACHE_MEMORY_SIZE (1 * 1024 * 1024) + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT_TASK_STACK_SIZE (32 * 1024) +#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT + +#define CONFIGURE_INIT + +#include diff --git a/libbsd/libdl/libdl.conf b/libbsd/libdl/libdl.conf new file mode 100644 index 0000000..abc4663 --- /dev/null +++ b/libbsd/libdl/libdl.conf @@ -0,0 +1,2 @@ +*.a +x diff --git a/libbsd/libdl/wscript b/libbsd/libdl/wscript new file mode 100644 index 0000000..22e1185 --- /dev/null +++ b/libbsd/libdl/wscript @@ -0,0 +1,126 @@ +# Copyright 2018 Chris Johns (chrisj@rtems.org) +# +# This file's license is 2-clause BSD as in this distribution's LICENSE.2 file. +# + +# +# This example shows: +# 1. How to build a runtime loadable application using waf and rtems_waf. +# 2. Runtime loading of object files from archives held on the target. +# +# The example's executable is large. +# +# Note: The archives and object files and placed in the root file system so the +# exapmle can run on as many BSPs as possible. A real system with +# non-volatile storage and a supported file system can hold these files +# lowering the executable's memory footprint. +# + +# Waf build script for an RTEMS Hello +import rtems_waf.rtems as rtems +import rtems_waf.rtems_bsd as rtems_bsd +import rtems_waf.rootfs as rtems_rootfs +import rtems_waf.dl as rtems_dl + +def configure(conf): + # + # The path to the following libraries. These are loaded onto the target. + # + rtems.check_lib_path(conf, lib = 'c') + rtems.check_lib_path(conf, lib = 'm') + rtems.check_lib_path(conf, lib = 'bsd', libpath = conf.env.LIBPATH) + +def build(bld): + rtems.build(bld) + + if not rtems_bsd.check_net_config(bld): + bld.fatal('libbsd libdl example needs a network config') + + # + # Build and copy the files to make a target file system. + # + bld.objects(features = 'c', + target = 'dl-objs', + source = ['dl_libbsd.c'], + idx = 101, # hack to find the object file + defines = bld.env.NET_CONFIG_DEFINES.split(',')) + + # + # Strip the object files and archives that are loaded onto the embedded + # target's file system of debug information. + # + rtems_dl.strip_debug_info(bld, + target = 'dl_libbsd.o', + source = 'dl_libbsd.c.101.o') + rtems_dl.strip_debug_info(bld, + target = 'libc.a', + source = bld.env.LIBPATH_libc) + rtems_dl.strip_debug_info(bld, + target = 'libm.a', + source = bld.env.LIBPATH_libm) + rtems_dl.strip_debug_info(bld, + target = 'libbsd.a', + source = bld.env.LIBPATH_libbsd) + + rtems_dl.ranlib(bld, 'libc.a') + rtems_dl.ranlib(bld, 'libm.a') + rtems_dl.ranlib(bld, 'libbsd.a') + + bld.add_group('dl-objs') + + # + # Build the root file system from the list of files. The fields are: + # 1. The build name + # 2. Source file + # 3. Target file in the file system + # + fs_files = [('rootfs-dl_libbsd', + bld.path.find_or_declare('dl_libbsd.o'), + 'dl_libbsd.o'), + ('rootfs-libdl-conf', + 'libdl.conf', + 'etc/libdl.conf'), + ('rootfs-libc', + bld.path.find_or_declare('libc.a'), + 'lib/libc.a'), + ('rootfs-libm', + bld.path.find_or_declare('libm.a'), + 'lib/libm.a'), + ('rootfs-libbsd.a', + bld.path.find_or_declare('libbsd.a'), + 'lib/libbsd.a')] + rtems_rootfs.build(bld, + name = 'libbsd-dl-rootfs', + root = 'rootfs', + files = fs_files) + + # + # Base image application that loads the libbsd initialisation + # + bld.objects(features = 'c', + target = 'exe-objs', + source = ['dl_main.c'], + includes = bld.path.get_bld().abspath()) + + # + # Phase 1 link, this contains the symbols in the base kernel image and is + # used to generate the symbol table. + # + libbsd_libdl_uses = ['exe-objs', 'libbsd-dl-rootfs-obj'] + bld(features = 'c cprogram', + target = 'libbsd-libdl.exe.pre', + use = libbsd_libdl_uses) + + # + # Create a symbol table. This is an object file linked to the base kernel + # imagge. The objects in the phase 1 link must match the objects in the + # phase 2 link. + # + rtems_dl.syms(bld, target = 'dl-syms.o', source = 'libbsd-libdl.exe.pre') + + # + # Phase 2 link, this is the target executable. + # + bld(features = 'c cprogram', + target = 'libbsd-libdl.exe', + use = libbsd_libdl_uses + ['dl-syms.o']) diff --git a/libbsd/wscript b/libbsd/wscript new file mode 100644 index 0000000..46d9b90 --- /dev/null +++ b/libbsd/wscript @@ -0,0 +1,14 @@ +# Copyright 2013 Gedare Bloom (gedare@rtems.org) +# +# This file's license is 2-clause BSD as in this distribution's LICENSE.2 file. +# + +import rtems_waf.rtems as rtems +import rtems_waf.rtems_bsd as rtems_bsd + +def configure(conf): + conf.recurse('libdl') + +def build(bld): + if rtems_bsd.check_libbsd(bld): + bld.recurse('libdl') diff --git a/wscript b/wscript index 4f5705b..eea7056 100644 --- a/wscript +++ b/wscript @@ -11,6 +11,7 @@ rtems_version = "5" try: import rtems_waf.rtems as rtems + import rtems_waf.rtems_bsd as rtems_bsd except: print('error: no rtems_waf git submodule; see README.waf') import sys @@ -21,9 +22,14 @@ def init(ctx): def options(opt): rtems.options(opt) + rtems_bsd.options(opt) + +def bsp_configure(conf, arch_bsp): + rtems_bsd.bsp_configure(conf, arch_bsp, mandatory = False) + conf.recurse('libbsd') def configure(conf): - rtems.configure(conf) + rtems.configure(conf, bsp_configure = bsp_configure) def build(bld): rtems.build(bld) @@ -42,6 +48,7 @@ def build(bld): bld.recurse('posix_api') bld.recurse('cxx') bld.recurse('c11') + bld.recurse('libbsd') def rebuild(ctx): import waflib.Options -- cgit v1.2.3