New TCP/IP System Initialization
Sebastian Huber
sebastian.huber at embedded-brains.de
Wed Apr 4 07:10:44 UTC 2012
Hi,
let me explain the FreeBSD initialization a bit more. The FreeBSD kernel is
not a library like the RTEMS kernel. It is a bunch of object files linked
together. If we have a library, then creating the executable is simple. We
begin with a start symbol and recursively resolve all references. With a bunch
of object files linked together we need a different mechanism. Most object
files don't know each other. Lets say we have a driver module. The rest of
the system has no references to this driver module. The driver module needs a
way to tell the rest of the system: Hey, kernel I am here, please use my services!
This registration of independent components is performed by SYSINIT(9) and
specializations:
http://www.freebsd.org/cgi/man.cgi?query=SYSINIT&sektion=9&apropos=0&manpath=FreeBSD+9.0-RELEASE
The SYSINIT(9) uses some global data structures that are placed in a certain
section. In the linker command file we need this:
.robsdsets : {
_bsd__start_set_modmetadata_set = .;
*(_bsd_set_modmetadata_set);
_bsd__stop_set_modmetadata_set = .;
_bsd__start_set_sysctl_set = .;
*(_bsd_set_sysctl_set);
_bsd__stop_set_sysctl_set = .;
} > REGION_RODATA AT > REGION_RODATA_LOAD
.rwbsdsets : {
_bsd__start_set_sysinit_set = .;
*(_bsd_set_sysinit_set);
_bsd__stop_set_sysinit_set = .;
} > REGION_DATA AT > REGION_DATA_LOAD
Here you can see, that these global data structures are collected into
continuous memory areas. This memory area can be identified by start and stop
symbols. This constructs a table of uniform items.
The low level FreeBSD code calls at some time during the initialization the
mi_startup() function (machine independent startup). This function will sort
the SYSINIT(9) set and call handler functions which perform further
initialization. The last step is the scheduler invocation.
This is also explained in "The Design and Implementation of the FreeBSD
Operating System" section 14.3 "Kernel Initialization".
On 04/03/2012 10:01 PM, Joel Sherrill wrote:
> Hi,
>
> In looking at what Sebastian has done in the test usb01,
> I see it defines that it needs some core devices, then
> includes rtems-bsd-sysinit.h which ensures they are
> referenced and pulled into the executable.
In RTEMS we have a library and not a bunch of object files. Thus we need a way
to pull-in the desired services out of the libbsd. Here the
"rtems-bsd-sysinit.h" comes into play. The SYSINIT(9) macros have been
modified and extended for RTEMS in "sys/kernel.h":
#ifndef __rtems__
#define C_SYSINIT(uniquifier, subsystem, order, func, ident) \
static struct sysinit uniquifier ## _sys_init = { \
subsystem, \
order, \
func, \
(ident) \
}; \
DATA_SET(sysinit_set,uniquifier ## _sys_init)
#else /* __rtems__ */
#define SYSINIT_ENTRY_NAME(uniquifier) \
_bsd_ ## uniquifier ## _sys_init
#define SYSINIT_REFERENCE_NAME(uniquifier) \
_bsd_ ## uniquifier ## _sys_init_ref
#define C_SYSINIT(uniquifier, subsystem, order, func, ident) \
struct sysinit SYSINIT_ENTRY_NAME(uniquifier) = { \
subsystem, \
order, \
func, \
(ident) \
}; \
DATA_SET(sysinit_set,SYSINIT_ENTRY_NAME(uniquifier))
#define SYSINIT_REFERENCE(uniquifier) \
extern struct sysinit SYSINIT_ENTRY_NAME(uniquifier); \
static struct sysinit const * const \
SYSINIT_REFERENCE_NAME(uniquifier) __used \
= &SYSINIT_ENTRY_NAME(uniquifier)
#define SYSINIT_MODULE_REFERENCE(mod) \
SYSINIT_REFERENCE(mod ## module)
#define SYSINIT_DRIVER_REFERENCE(driver, bus) \
SYSINIT_MODULE_REFERENCE(driver ## _ ## bus)
#endif /* __rtems__ */
Here you see that the SYSINIT(9) entries are no longer static. The
*_REFERENCE() macros will create references to the corresponding modules which
are later resolved by the linker. The application has to provide an object
file with references to all required FreeBSD modules.
The FreeBSD device model is quite elaborated (with follow-ups):
http://www.freebsd.org/cgi/man.cgi?query=driver&sektion=9&apropos=0&manpath=FreeBSD+9.0-RELEASE
The devices form a tree with the Nexus device at a high-level. This Nexus
device is architecture specific in FreeBSD. In RTEMS we have our own Nexus
device, see "rtems-bsd-nexus.c". It uses a table to add child devices:
const char *const _bsd_nexus_devices [] = {
#ifdef NEED_USB_OHCI
"ohci",
#endif
#ifdef NEED_USB_EHCI
"ehci",
#endif
#ifdef NEED_SDHC
"sdhci",
#endif
NULL
};
This table must be provided by the application.
> + Where are the sysinit routines run?
In mi_startup().
> + What calls that?
The function rtems_bsd_initialize().
> + Other than referencing the desired NICs, any ideas
> on what other net components need to be pulled in?
You should grep for the SYSINIT(9) (with specializations, see man page) macros
in the network code to identify its components.
>
> Any other explanations that can be offered would
> be appreciated.
>
--
Sebastian Huber, embedded brains GmbH
Address : Obere Lagerstr. 30, D-82178 Puchheim, Germany
Phone : +49 89 18 90 80 79-6
Fax : +49 89 18 90 80 79-9
E-Mail : sebastian.huber at embedded-brains.de
PGP : Public key available on request.
Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.
More information about the devel
mailing list