Changeset 8a4f070 in rtems-libbsd for libbsd.txt

Apr 16, 2012, 10:23:55 AM (7 years ago)
Sebastian Huber <sebastian.huber@…>
4.11, 7ece7548c1b05cf6bb10e6708b83b2401d45c250, freebsd-9.3, 29cc431e0bcfe059d65ac3019f53eeafa5064ae8

Elaborate RTEMS libbsd initialization

1 edited


  • libbsd.txt

    ra3d2498 r8a4f070  
    264 == Initialization of RTEMS Libbsd
    266 The initialization of the RTEMS Libbsd is based on the FreeBSD SYSINIT
    267 infrastructure. This is simply because we are initializing a subset of
    268 FreeBSD. For details refer to
    270 The key to initializing a system is to ensure that the desired device
    271 drivers are explicitly pulled into the linked application. This plus
    272 linking against the Libsd library will pull in the necessary FreeBSD
    273 infrastructure. The SYSINIT structures are automatically built at link
    274 time and the various initialization routines will thus be executed in'
    275 the correct order.
    277 XXX This needs more details.
     264== Initialization of RTEMS libbsd
     266The initialization of the RTEMS libbsd is based on the FreeBSD SYSINIT(9)
     267infrastructure.  The key to initializing a system is to ensure that the desired
     268device drivers are explicitly pulled into the linked application.  This plus
     269linking against the libbsd library will pull in the necessary FreeBSD
     272The FreeBSD kernel is not a library like the RTEMS kernel.  It is a bunch of
     273object files linked together.  If we have a library, then creating the
     274executable is simple.  We begin with a start symbol and recursively resolve all
     275references.  With a bunch of object files linked together we need a different
     276mechanism.  Most object files don't know each other.  Lets say we have a driver
     277module.  The rest of the system has no references to this driver module.  The
     278driver module needs a way to tell the rest of the system: Hey, kernel I am
     279here, please use my services!
     281This registration of independent components is performed by SYSINIT(9) and
     286The SYSINIT(9) uses some global data structures that are placed in a certain
     287section.  In the linker command file we need this:
     291.robsdsets : {
     292    _bsd__start_set_modmetadata_set = .;
     293    *(_bsd_set_modmetadata_set);
     294    _bsd__stop_set_modmetadata_set = .;
     295    _bsd__start_set_sysctl_set = .;
     296    *(_bsd_set_sysctl_set);
     297    _bsd__stop_set_sysctl_set = .;
     300.rwbsdsets : {
     301    _bsd__start_set_sysinit_set = .;
     302    *(_bsd_set_sysinit_set);
     303    _bsd__stop_set_sysinit_set = .;
     307Here you can see, that these global data structures are collected into
     308continuous memory areas.  This memory area can be identified by start and stop
     309symbols.  This constructs a table of uniform items.
     311The low level FreeBSD code calls at some time during the initialization the
     312mi_startup() function (machine independent startup).  This function will sort
     313the SYSINIT(9) set and call handler functions which perform further
     314initialization.  The last step is the scheduler invocation.
     316The SYSINIT(9) routines are run in mi_startup() which is called by
     319This is also explained in "The Design and Implementation of the FreeBSD
     320Operating System" section 14.3 "Kernel Initialization".
     322In RTEMS we have a library and not a bunch of object files.  Thus we need a way
     323to pull-in the desired services out of the libbsd.  Here the
     324"rtems-bsd-sysinit.h" comes into play.  The SYSINIT(9) macros have been
     325modified and extended for RTEMS in "sys/kernel.h":
     329#ifndef __rtems__
     330#define    C_SYSINIT(uniquifier, subsystem, order, func, ident) \
     331    static struct sysinit uniquifier ## _sys_init = { \
     332        subsystem, \
     333        order, \
     334        func, \
     335        (ident) \
     336    }; \
     337    DATA_SET(sysinit_set,uniquifier ## _sys_init)
     338#else /* __rtems__ */
     339#define    SYSINIT_ENTRY_NAME(uniquifier) \
     340    _bsd_ ## uniquifier ## _sys_init
     341#define    SYSINIT_REFERENCE_NAME(uniquifier) \
     342    _bsd_ ## uniquifier ## _sys_init_ref
     343#define    C_SYSINIT(uniquifier, subsystem, order, func, ident) \
     344    struct sysinit SYSINIT_ENTRY_NAME(uniquifier) = { \
     345        subsystem, \
     346        order, \
     347        func, \
     348        (ident) \
     349    }; \
     350    DATA_SET(sysinit_set,SYSINIT_ENTRY_NAME(uniquifier))
     351#define    SYSINIT_REFERENCE(uniquifier) \
     352    extern struct sysinit SYSINIT_ENTRY_NAME(uniquifier); \
     353    static struct sysinit const * const \
     354    SYSINIT_REFERENCE_NAME(uniquifier) __used \
     355    = &SYSINIT_ENTRY_NAME(uniquifier)
     356#define    SYSINIT_MODULE_REFERENCE(mod) \
     357    SYSINIT_REFERENCE(mod ## module)
     358#define    SYSINIT_DRIVER_REFERENCE(driver, bus) \
     359    SYSINIT_MODULE_REFERENCE(driver ## _ ## bus)
     360#endif /* __rtems__ */
     363Here you see that the SYSINIT(9) entries are no longer static.  The
     364*_REFERENCE() macros will create references to the corresponding modules which
     365are later resolved by the linker.  The application has to provide an object
     366file with references to all required FreeBSD modules.
     368The FreeBSD device model is quite elaborated (with follow-ups):
     372The devices form a tree with the Nexus device at a high-level.  This Nexus
     373device is architecture specific in FreeBSD.  In RTEMS we have our own Nexus
     374device, see "rtems-bsd-nexus.c".  It uses a table to add child devices:
     378const char *const _bsd_nexus_devices [] = {
     379    #ifdef NEED_USB_OHCI
     380        "ohci",
     381    #endif
     382    #ifdef NEED_USB_EHCI
     383        "ehci",
     384    #endif
     385    #ifdef NEED_SDHC
     386        "sdhci",
     387    #endif
     388    NULL
     392This table must be provided by the application.
    279394=== SYSCTL_NODE Example
Note: See TracChangeset for help on using the changeset viewer.