freebsd-dev/sys/sys/firmware.h
Luigi Rizzo 33d5497079 Cleanup and document the implementation of firmware(9) based on
a version that i posted earlier on the -current mailing list,
and subsequent feedback received.

The core of the change is just in sys/firmware.h and kern/subr_firmware.c,
while other files are just adaptation of the clients to the ABI change
(const-ification of some parameters and hiding of internal info,
so this is fully compatible at the binary level).

In detail:
- reduce the amount of information exported to clients in struct firmware,
  and constify the pointer;

- internally, document and simplify the implementation of the various
  functions, and make sure error conditions are dealt with properly.

The diffs are large, but the code is really straightforward now (i hope).

Note also that there is a subtle issue with the implementation of
firmware_register(): currently, as in the previous version, we just
store a reference to the 'imagename' argument, but we should rather
copy it because there is no guarantee that this is a static string.
I realised this while testing this code, but i prefer to fix it in
a later commit -- there is no regression with respect to the past.

Note, too, that the version in RELENG_6 has various bugs including
missing locks around the module release calls, mishandling of modules
loaded by /boot/loader, and so on, so an MFC is absolutely necessary
there.  I was just postponing it until this cleanup to avoid doing
things twice.

MFC after: 1 week
2007-02-15 17:21:31 +00:00

65 lines
2.9 KiB
C

/*-
* Copyright (c) 2005, Sam Leffler <sam@errno.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _SYS_FIRMWARE_H_
#define _SYS_FIRMWARE_H_
/*
* Loadable firmware support.
*
* The firmware abstraction provides an interface for loading firmware
* images into the kernel and making them available to clients.
*
* Firmware images are usually embedded in kernel loadable modules that can
* be loaded on-demand or pre-loaded as desired. Modules may contain
* one or more firmware images that are stored as opaque data arrays
* and registered with a unique string name. Clients request
* firmware by name, and are returned a struct firmware * below on success.
* The kernel keeps track of references to firmware images to allow/prevent
* module/data unload.
*
* When multiple images are stored in one module, the first image is
* treated as the master with the other images holding references
* to it. This means that to unload the module each dependent/subimage
* must first have its references removed.
* In order for automatic loading to work, the master image must have
* the same name as the module it is embedded into.
*/
struct firmware {
const char *name; /* system-wide name */
const void *data; /* location of image */
size_t datasize; /* size of image in bytes */
unsigned int version; /* version of the image */
};
const struct firmware *firmware_register(const char *,
const void *, size_t, unsigned int, const struct firmware *);
int firmware_unregister(const char *);
const struct firmware *firmware_get(const char *);
#define FIRMWARE_UNLOAD 0x0001 /* unload if unreferenced */
void firmware_put(const struct firmware *, int);
#endif /* _SYS_FIRMWARE_H_ */