33#include <sys/kernel.h>
34#include <sys/malloc.h>
36#include <sys/taskqueue.h>
41#include <sys/linker.h>
42#include <sys/firmware.h>
45#include <sys/module.h>
46#include <sys/eventhandler.h>
48#include <sys/filedesc.h>
92#define FW_UNLOAD 0x100
116#define PRIV_FW(x) ((struct priv_fw *) \
117 ((intptr_t)(x) - offsetof(struct priv_fw, fw)) )
129static struct task firmware_unload_task;
134static struct mtx firmware_mtx;
135MTX_SYSINIT(firmware, &firmware_mtx,
"firmware table", MTX_DEF);
137static MALLOC_DEFINE(M_FIRMWARE,
"firmware",
"device firmware images");
147lookup(
const char *
name)
151 mtx_assert(&firmware_mtx, MA_OWNED);
153 LIST_FOREACH(fp, &firmware_table, link) {
154 if (fp->fw.name != NULL && strcasecmp(
name, fp->fw.name) == 0)
166const struct firmware *
168 unsigned int version,
const struct firmware *
parent)
173 mtx_lock(&firmware_mtx);
174 frp = lookup(imagename);
176 mtx_unlock(&firmware_mtx);
177 printf(
"%s: image %s already registered!\n",
178 __func__, imagename);
181 mtx_unlock(&firmware_mtx);
183 frp =
malloc(
sizeof(*frp), M_FIRMWARE, M_WAITOK | M_ZERO);
184 name = strdup(imagename, M_FIRMWARE);
186 mtx_lock(&firmware_mtx);
187 if (lookup(imagename) != NULL) {
189 mtx_unlock(&firmware_mtx);
191 free(frp, M_FIRMWARE);
196 frp->fw.datasize = datasize;
197 frp->fw.version = version;
200 LIST_INSERT_HEAD(&firmware_table, frp, link);
201 mtx_unlock(&firmware_mtx);
203 printf(
"firmware: '%s' version %u: %zu bytes loaded at %p\n",
204 imagename, version, datasize,
data);
219 mtx_lock(&firmware_mtx);
220 fp = lookup(imagename);
229 }
else if (fp->
refcnt != 0) {
232 LIST_REMOVE(fp, link);
233 free(__DECONST(
char *, fp->fw.name), M_FIRMWARE);
234 free(fp, M_FIRMWARE);
237 mtx_unlock(&firmware_mtx);
257 printf(
"%s: could not load firmware image, error %d\n",
259 mtx_lock(&firmware_mtx);
263 mtx_lock(&firmware_mtx);
265 if (fp == NULL || fp->file != NULL) {
266 mtx_unlock(&firmware_mtx);
268 printf(
"%s: firmware image loaded, "
269 "but did not register\n", fwli->
imagename);
271 mtx_lock(&firmware_mtx);
277 mtx_unlock(&firmware_mtx);
287const struct firmware *
290 struct task fwload_task;
294 mtx_lock(&firmware_mtx);
295 fp = lookup(imagename);
302 if (
priv_check(td, PRIV_FIRMWARE_LOAD) != 0 ||
304 mtx_unlock(&firmware_mtx);
305 printf(
"%s: insufficient privileges to "
306 "load firmware image %s\n", __func__, imagename);
319 TASK_INIT(&fwload_task, 0,
loadimage, (
void *)&fwli);
322 msleep((
void *)&fwli, &firmware_mtx, 0,
"fwload", 0);
330 mtx_unlock(&firmware_mtx);
334 if (fp->
refcnt == 0 && fp->parent != NULL)
337 mtx_unlock(&firmware_mtx);
341const struct firmware *
362 mtx_lock(&firmware_mtx);
365 if (fp->parent != NULL)
367 if (
flags & FIRMWARE_UNLOAD)
372 mtx_unlock(&firmware_mtx);
393 struct task *setroot_task;
395 setroot_task =
malloc(
sizeof(
struct task), M_TEMP, M_NOWAIT);
396 if (setroot_task != NULL) {
400 printf(
"%s: no memory for task!\n", __func__);
416 mtx_lock(&firmware_mtx);
418 LIST_FOREACH(fp, &firmware_table, link) {
419 if (fp->file == NULL || fp->
refcnt != 0 ||
429 fp->flags &= ~FW_UNLOAD;
435 mtx_unlock(&firmware_mtx);
437 mtx_lock(&firmware_mtx);
445 mtx_unlock(&firmware_mtx);
460 TASK_INIT(&firmware_unload_task, 0,
unloadentry, NULL);
477 mtx_lock(&firmware_mtx);
478 LIST_FOREACH(fp, &firmware_table, link)
480 mtx_unlock(&firmware_mtx);
484 LIST_FOREACH(fp, &firmware_table, link) {
485 if (fp->fw.name != NULL) {
486 printf(
"%s: image %s still active, %d refs\n",
487 __func__, fp->fw.name, fp->
refcnt);
device_property_type_t type
MALLOC_DEFINE(M_BINMISC, KMOD_NAME, "misc binary image activator")
void pwd_ensure_dirs(void)
MTX_SYSINIT(et_eventtimers_init, &et_eventtimers_mtx, "et_mtx", MTX_DEF)
int linker_reference_module(const char *modname, struct mod_depend *verinfo, linker_file_t *result)
int linker_release_module(const char *modname, struct mod_depend *verinfo, linker_file_t lf)
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
int priv_check(struct thread *td, int priv)
int securelevel_gt(struct ucred *cr, int level)
void wakeup_one(const void *ident)
static void unloadentry(void *unused1, int unused2)
static moduledata_t firmware_mod
int firmware_unregister(const char *imagename)
const struct firmware * firmware_get(const char *imagename)
DECLARE_MODULE(firmware, firmware_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST)
void firmware_put(const struct firmware *p, int flags)
static int firmware_modevent(module_t mod, int type, void *unused)
static void set_rootvnode(void *arg, int npending)
static void firmware_mountroot(void *arg)
EVENTHANDLER_DEFINE(mountroot, firmware_mountroot, NULL, 0)
const struct firmware * firmware_get_flags(const char *imagename, uint32_t flags)
MODULE_VERSION(firmware, 1)
static void loadimage(void *arg, int npending __unused)
static LIST_HEAD(priv_fw)
const struct firmware * firmware_register(const char *imagename, const void *data, size_t datasize, unsigned int version, const struct firmware *parent)
int printf(const char *fmt,...)
int taskqueue_enqueue(struct taskqueue *queue, struct task *task)
int taskqueue_start_threads(struct taskqueue **tqp, int count, int pri, const char *name,...)
struct taskqueue * taskqueue_create(const char *name, int mflags, taskqueue_enqueue_fn enqueue, void *context)
void taskqueue_free(struct taskqueue *queue)
void taskqueue_drain(struct taskqueue *queue, struct task *task)
void taskqueue_thread_enqueue(void *context)