27 #include <sys/cdefs.h>
30 #include <sys/param.h>
31 #include <sys/kernel.h>
32 #include <sys/malloc.h>
33 #include <sys/queue.h>
34 #include <sys/taskqueue.h>
35 #include <sys/systm.h>
37 #include <sys/mutex.h>
38 #include <sys/errno.h>
39 #include <sys/linker.h>
40 #include <sys/firmware.h>
43 #include <sys/module.h>
44 #include <sys/eventhandler.h>
46 #include <sys/filedesc.h>
47 #include <sys/vnode.h>
58 #define FW_INUSE(p) ((p)->file != NULL || (p)->fw.name != NULL)
91 #define FW_UNLOAD 0x100
115 #define PRIV_FW(x) ((struct priv_fw *) \
116 ((intptr_t)(x) - offsetof(struct priv_fw, fw)) )
124 #define FIRMWARE_MAX 50
154 if (empty_slot == NULL)
159 if (fp->
fw.name != NULL && strcasecmp(name, fp->
fw.name) == 0)
164 return (i < FIRMWARE_MAX ) ? fp : NULL;
173 const struct firmware *
175 unsigned int version,
const struct firmware *
parent)
183 match =
lookup(imagename, &frp);
186 printf(
"%s: image %s already registered!\n",
187 __func__, imagename);
192 printf(
"%s: cannot register image %s, firmware table full!\n",
193 __func__, imagename);
196 bzero(frp,
sizeof(*frp));
197 frp->
fw.name = imagename;
199 frp->
fw.datasize = datasize;
200 frp->
fw.version = version;
205 printf(
"firmware: '%s' version %u: %zu bytes loaded at %p\n",
206 imagename, version, datasize, data);
222 fp =
lookup(imagename, NULL);
231 }
else if (fp->
refcnt != 0) {
234 linker_file_t x = fp->
file;
241 bzero(fp,
sizeof(
struct priv_fw));
252 struct thread *td = curthread;
253 char *imagename = arg;
262 if (td->td_proc->p_fd->fd_rdir == NULL) {
263 printf(
"%s: root not mounted yet, no way to load image\n",
269 printf(
"%s: could not load firmware image, error %d\n",
275 fp =
lookup(imagename, NULL);
276 if (fp == NULL || fp->
file != NULL) {
279 printf(
"%s: firmware image loaded, "
280 "but did not register\n", imagename);
297 const struct firmware *
300 struct task fwload_task;
305 fp =
lookup(imagename, NULL);
312 if (
priv_check(td, PRIV_FIRMWARE_LOAD) != 0 ||
315 printf(
"%s: insufficient privileges to "
316 "load firmware image %s\n", __func__, imagename);
325 TASK_INIT(&fwload_task, 0,
loadimage, __DECONST(
void *,
334 fp =
lookup(imagename, NULL);
366 if (flags & FIRMWARE_UNLOAD)
380 struct thread *td = curthread;
381 struct proc *p = td->td_proc;
383 FILEDESC_XLOCK(p->p_fd);
384 if (p->p_fd->fd_cdir == NULL) {
388 if (p->p_fd->fd_rdir == NULL) {
392 FILEDESC_XUNLOCK(p->p_fd);
404 struct task *setroot_task;
406 setroot_task =
malloc(
sizeof(
struct task), M_TEMP, M_NOWAIT);
407 if (setroot_task != NULL) {
411 printf(
"%s: no memory for task!\n", __func__);
433 for (i = 0; i < limit; i++) {
438 if (fp->
fw.name == NULL || fp->
file == NULL ||
511 if (fp->
fw.name != NULL) {
512 printf(
"%s: image %p ref %d still active slot %d\n",
513 __func__, fp->
fw.name,
MTX_SYSINIT(firmware,&firmware_mtx,"firmware table", MTX_DEF)
void taskqueue_drain(struct taskqueue *queue, struct task *task)
int firmware_unregister(const char *imagename)
void * malloc(unsigned long size, struct malloc_type *mtp, int flags)
static void set_rootvnode(void *arg, int npending)
static struct mtx firmware_mtx
MODULE_VERSION(firmware, 1)
static struct task firmware_unload_task
static moduledata_t firmware_mod
void wakeup_one(void *ident)
static struct priv_fw * lookup(const char *name, struct priv_fw **empty_slot)
int priv_check(struct thread *td, int priv)
void firmware_put(const struct firmware *p, int flags)
static int firmware_modevent(module_t mod, int type, void *unused)
static void loadimage(void *arg, int npending)
static struct priv_fw firmware_table[FIRMWARE_MAX]
void taskqueue_free(struct taskqueue *queue)
DECLARE_MODULE(firmware, firmware_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST)
struct taskqueue * taskqueue_create(const char *name, int mflags, taskqueue_enqueue_fn enqueue, void *context)
const struct firmware * firmware_get(const char *imagename)
void free(void *addr, struct malloc_type *mtp)
int printf(const char *fmt,...)
int linker_reference_module(const char *modname, struct mod_depend *verinfo, linker_file_t *result)
int taskqueue_enqueue(struct taskqueue *queue, struct task *task)
int linker_release_module(const char *modname, struct mod_depend *verinfo, linker_file_t lf)
static struct taskqueue * firmware_tq
int taskqueue_start_threads(struct taskqueue **tqp, int count, int pri, const char *name,...)
int securelevel_gt(struct ucred *cr, int level)
void taskqueue_thread_enqueue(void *context)
static void unloadentry(void *unused1, int unused2)
const struct firmware * firmware_register(const char *imagename, const void *data, size_t datasize, unsigned int version, const struct firmware *parent)
static void firmware_mountroot(void *arg)
EVENTHANDLER_DEFINE(mountroot, firmware_mountroot, NULL, 0)