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