diff --git a/share/man/man9/firmware.9 b/share/man/man9/firmware.9 index 2ff1debd419b..233ea2acaf7c 100644 --- a/share/man/man9/firmware.9 +++ b/share/man/man9/firmware.9 @@ -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 + +.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 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