Document a little more the firmware subsystem.

Apart from minor cleanup of the text, it should document
in reasonable detail what the status of the code is.
RELENG_6 has some minor differences there in the way automatic
loading/unloading is handled, but hopefully this should be
fixed by MFC time.

The examples come from Max Laier and Sam Leffler.

MFC after: 1 week
This commit is contained in:
Luigi Rizzo 2007-02-09 19:08:07 +00:00
parent 983f970981
commit 97070dd5e0

View File

@ -65,55 +65,203 @@ struct firmware {
.Sh DESCRIPTION
The
.Nm firmware
abstraction provides a convenient interface for loading firmware
images into the kernel.
Specially crafted kernel modules are used to hold the firmware images.
abstraction provides a convenient interface for loading
.Nm firmware images
into the kernel, and for accessing such images from kernel components.
.Pp
The function
.Fn firmware_register
is used on load of such modules to register contained firmware images.
The arguments to
.Fn firmware_register
include a name that identifies the image for later requests to the
A
.Nm firmware image
(or
.Nm image
for brevity)
is an opaque block of data residing in kernel memory.
It is associated to a unique
.Nm imagename
which constitutes a search key, and to an integer
.Nm version
number, which is also an opaque piece of information for the
firmware subsystem.
.Pp
An image is registered with the
.Nm firmware
system, a pointer to the actual image, the size of the image and an optional
parent image.
The parent image is used to keep track of references to a given module so that
it can be unloaded on last reference.
subsystem by calling the function
.Fn firmware_register ,
and unregistered by calling
.Fn firmware_unregister .
These functions are usually (but not exclusively) performed by
specially crafted kernel modules that contain the firmware image.
The modules can be statically compiled in the kernel, or loaded by
.Nm /boot/loader ,
manually at runtime, or on demand by the firmware subsystem.
.Pp
.Nm Clients
of the firmware subsystem can request access to a given image
by calling the function
.Fn firmware_get
with the
.Nm imagename
they want as an argument. If a matching image is not already registered,
the firmware subsystem will try to load it using the
mechanisms specified below (typically, a kernel module
with
.Nm the same name
as the image).
.Sh API DESCRIPTION
The kernel
.Nm firmware API
is made of the following functions:
.Pp
.Fn firmware_register
registers with the kernel an image of size
.Nm datasize
located at address
.Nm data ,
under the name
.Nm imagename .
.Nm parent
is and a pointer to the parent image, if any.
.Pp
The function returns NULL on error (e.g. because an
image with the same name already exists, or the image
table is full), or a
.Ft const struct firmware *
pointer to the image requested.
.Pp
The function
.Fn firmware_unregister
removes the firmware image identified by the name from the system if there
are no pending references or returns an error otherwise.
tries to unregister the firmware image
.Nm imagename
from the system. The function is successful and returns 0
if there are no pending references to the image, otherwise
it does not unregister the image and returns EBUSY.
.Pp
The function
.Fn firmware_get
returns the requested firmware image.
If the image is not yet registered with the system,
.Fn firmware_get
tries to load a module with the corresponding name.
This involves the linker subsystem and disk access which is why
the function tries to load it.
This involves the linker subsystem and disk access, so
.Fn firmware_get
must not be called with any locks (except for
.Va Giant ) .
The caller must also have a process context so filesystem state such as
the root vnode is defined (e.g. you cannot load from a taskqueue thread).
.Pp
On success,
.Fn firmware_get
returns a pointer to the image description and increases the reference count
for this image.
for this image. On failure, the function returns NULL.
.Pp
The function
.Fn firmware_put
is used to drop the reference to a firmware image.
drops a reference to a firmware image.
The
.Fa flags
argument may be set to
.Dv FIRMWARE_UNLOAD
to indicate that the caller wishes to unload the corresponding module if the
image becomes unreferenced.
.Sh SEE ALSO
.Xr module 9
to indicate that
firmware_put is free to reclaim resources associated with
the firmware image if this is the last reference.
.Sh FIRMWARE LOADING MECHANISMS
As mentioned before, any component of the system can register
firmware images at any time by simply calling
.Fn firmware_register .
.Pp
.Pa /usr/share/examples/kld
This is typically done when a module containing
a firmware image is given control,
whether compiled in, or preloaded by
.Nm /boot/loader ,
or manually loaded with
.Xr kldload 8 .
However, a system can implement additional mechanisms to bring
these images in memory before calling
.Fn firmware_register .
.Pp
When
.Fn firmware_get
does not find the requested image, it tries to load it using
one of the available loading mechanisms.
At the moment, there is only one, namely
.Nm Loadable kernel modules :
.Pp
A firmware image named
.Nm foo
is looked up by trying to load the module named
.Nm foo.ko ,
using the facilities described in
.Xr kld 4 .
In particular, images are looked up in the directories specified
by the sysctl variable
.Nm kern.module_path
which on most systems defaults to
.Nm /boot/kernel;/boot/modules .
.Pp
Note that in case a module contains multiple images,
the caller should first request a
.Fn firmware_get
for the first image contained in the module, followed by requests
for the other images.
.Sh BUILDING FIRMWARE LOADABLE MODULES
A firmware module is built by embedding the
.Nm firmware image
into a suitable loadable kernel module that calls
.Fn firmware_register
on loading, and
.Fn firmware_unregister
on unloading.
.Pp
Various system scripts and makefiles let you build a module
by simply writing a Makefile with the following entries:
.Bd -literal
KMOD= imagename
FIRMWS= image_file:imagename[:version]
.include <bsd.kmod.mk>
.Ed
where KMOD is the basename of the module; FIRMWS is a list of
colon-separated tuples indicating the image_file's to be embedded
in the module, the imagename and version of each firmware image.
.Pp
If you need to embed firmware images into a system, you should write
appropriate entries in the <files.arch> file, e.g. this example is
from
.Nm sys/arm/xscale/ixp425/files.ixp425:
.Bd -literal
ixp425_npe_fw.c optional npe_fw \\
compile-with "${AWK} -f $S/tools/fw_stub.awk \\
IxNpeMicrocode.dat:npe_fw -mnpe -c${.TARGET}" \\
no-implicit-rule before-depend local \\
clean "ixp425_npe_fw.c"
#
# NB: ld encodes the path in the binary symbols generated for the
# firmware image so link the file to the object directory to
# get known values for reference in the _fw.c file.
#
IxNpeMicrocode.fwo optional npe_fw \\
dependency "IxNpeMicrocode.dat" \\
compile-with "${LD} -b binary -d -warn-common \\
-r -d -o ${.TARGET} IxNpeMicrocode.dat" \\
no-implicit-rule \\
clean "IxNpeMicrocode.fwo"
IxNpeMicrocode.dat optional npe_fw \\
dependency ".PHONY" \\
compile-with "if [ -e $S/arm/xscale/ixp425/IxNpeMicrocode.dat ]; \\
then \\
ln -sf $S/arm/xscale/ixp425/IxNpeMicrocode.dat .; \\
else echo 'WARNING, no IxNpeMicrocode.dat file; you must obtain this from the Intel web site'; false; \\
fi" \\
no-obj no-implicit-rule \\
clean "IxNpeMicrocode.dat"
.Ed
.Pp
Note that generating the firmware modules in this way requires
the availability of the following tools:
.Xr awk ,
.Xr Make ,
the compiler and the linker.
.Sh SEE ALSO
.Xr module 9 ,
.Xr kld 4
.Pp
.Pa /usr/share/examples/kld/firmware
.Sh HISTORY
The
.Nm firmware